From 7d6f6ca93ab0d1f6eeb0da5c665bacaf78a53b8f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 21 Jul 2026 19:37:34 -0700 Subject: [PATCH 001/168] fix gdi text on mingw --- src/text/gdi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/text/gdi.c b/src/text/gdi.c index b764353..ab54664 100644 --- a/src/text/gdi.c +++ b/src/text/gdi.c @@ -180,19 +180,19 @@ static HANDLE WINAPI _AddFontMemResourceExPolyFill(PVOID pFileView, DWORD cjSize CHAR temp_path_dir[MAX_PATH]; CHAR temp_path_name[MAX_PATH]; HANDLE tempFile = NULL; - int hr; + DWORD hr; (void)pvResrved; hr = GetTempPathA(MAX_PATH, temp_path_dir); if(hr == 0) { printf("GetTempPathA error %08lX\n", hr); - return hr; + return NULL; } hr = GetTempFileNameA(temp_path_dir, TEXT("MILSKO"), 0, temp_path_name); if(hr == 0) { printf("GetTempFileNameA error %08lX\n", hr); - return hr; + return NULL; } printf("extracting mem font to %s\n", temp_path_name); @@ -223,14 +223,14 @@ static HANDLE WINAPI _AddFontMemResourceExPolyFill(PVOID pFileView, DWORD cjSize } } printf("CreateFileA error %08lX\n", err); - return hr; + return NULL; } success: hr = WriteFile(tempFile, pFileView, cjSize, NULL, NULL); if(hr != 0) { printf("WriteFile error %08lX\n", hr); - return 0; + return NULL; } *pNumFonts = AddFontResource(temp_path_name); From d3af13ebd655fdd1f5168468385642a88180dfb4 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 23 Jul 2026 11:45:01 +0900 Subject: [PATCH 002/168] drag and drop beginnings Reviewed-on: https://forgejo.nishi.boats/pyrite-dev/milsko/pulls/33 --- include/Mw/LowLevel.h | 7 ++ include/Mw/LowLevel/GDI.h | 13 ++ include/Mw/StringDefs.h | 4 + include/Mw/TypeDefs.h | 2 +- src/backend/cairo.c | 13 +- src/backend/call.c | 5 +- src/backend/classicmacos.c | 4 + src/backend/cocoa.m | 4 + src/backend/gdi.c | 221 +++++++++++++++++++++++++++++++++- src/backend/haiku.cc | 4 + src/backend/wayland/wayland.c | 4 + src/backend/x11.c | 4 + src/core.c | 10 ++ src/lowlevel.c | 5 +- src/widget/entry.c | 5 +- 15 files changed, 288 insertions(+), 17 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index a2be271..b58d54e 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -39,6 +39,7 @@ struct _MwLLCommon { int type; int coordinate_type; MwBool supports_transparency; + const char** known_mime_types; MwLLHandler handler; }; @@ -315,6 +316,12 @@ MWDECL void (*MwLLGetClipboard)(MwLL handle, int clipboard_type); MWDECL void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point); MWDECL void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect); +/*! + * @brief Setup drag and drop capabilities, should the user request it with MwNacceptsDnD + * @param handle Handle + */ +MWDECL void (*MwLLSetupDragAndDrop)(MwLL handle); + /*! * @brief Set any extra parameters for dark theme * @param handle Handle diff --git a/include/Mw/LowLevel/GDI.h b/include/Mw/LowLevel/GDI.h index e505b0a..6230a36 100644 --- a/include/Mw/LowLevel/GDI.h +++ b/include/Mw/LowLevel/GDI.h @@ -29,6 +29,11 @@ struct _MwLLGDI { int force_render; int get_clipboard; int get_darktheme; + + /* drag and drop */ + struct _MwLLGDIDropTarget* dropTarget; + struct _MwLLGDIDropSource* dropSource; + MwBool drag_update; }; struct _MwLLGDIColor { @@ -47,6 +52,14 @@ struct _MwLLGDIPixmap { HBITMAP hMask2; }; +struct _MwLLGDIDropTarget{ + struct IDropTargetVtbl *lpVtbl; + LONG refCount; + HWND hwnd; + MwLL handle; +}; +typedef struct _MwLLGDIDropTarget MwLLGDIDropTarget; + MWDECL int MwLLGDICallInit(void); MWDECL HCURSOR MwLLGDICreateCursor(MwCursor* image, MwCursor* mask); diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index b95fe93..5f9e3e4 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -53,6 +53,7 @@ #define MwNcolumnSpan "IcolumnSpan" #define MwNrowSpan "IrowSpan" #define MwNdisabled "Idisabled" +#define MwNacceptsDnD "IacceptsDnD" #define MwNtitle "Stitle" #define MwNtext "Stext" @@ -62,6 +63,8 @@ #define MwNforeground "Sforeground" #define MwNsubForeground "SsubForeground" #define MwNtitleForeground "StitleForeground" +#define MwNacceptedMimeType "SacceptedMimeType" + #define MwNvulkanExtension "SEvulkanExtension" #define MwNvulkanLayer "SEvulkanLayer" @@ -98,5 +101,6 @@ #define MwNdrawHandler "Cdraw" #define MwNclipboardHandler "Cclipboard" #define MwNdarkThemeHandler "CdarkTheme" +#define MwNdragAndDropHandler "CdragAndDrop" #endif diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 5989e1b..fbc91fa 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -274,7 +274,7 @@ struct _MwClass { MwHandlerChildrenProp children_prop_change; MwHandlerClipboardReceived clipboard; MwHandlerProps props_change; - void* reserved1; + MwHandler drag_and_drop; void* reserved2; void* reserved3; }; diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 0c26ff3..d70de1b 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -212,8 +212,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -255,11 +255,12 @@ static MwBool MwLLDoModernImpl(MwLL handle) { } static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} +static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/call.c b/src/backend/call.c index f84247f..0deffb4 100644 --- a/src/backend/call.c +++ b/src/backend/call.c @@ -52,8 +52,9 @@ MwLLSetClipboard = MwLLSetClipboardImpl; \ MwLLGetClipboard = MwLLGetClipboardImpl; \ \ - MwLLGetCursorCoord = MwLLGetCursorCoordImpl; \ - MwLLGetScreenSize = MwLLGetScreenSizeImpl; \ + MwLLGetCursorCoord = MwLLGetCursorCoordImpl; \ + MwLLGetScreenSize = MwLLGetScreenSizeImpl; \ + MwLLSetupDragAndDrop = MwLLSetupDragAndDropImpl; \ \ MwLLSetDarkTheme = MwLLSetDarkThemeImpl; \ MwLLDoModern = MwLLDoModernImpl; \ diff --git a/src/backend/classicmacos.c b/src/backend/classicmacos.c index d3da454..f063551 100644 --- a/src/backend/classicmacos.c +++ b/src/backend/classicmacos.c @@ -347,6 +347,10 @@ static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { } +static void MwLLSetupDragAndDropImpl(MwLL handle) { + (void)handle; +} + static void MwLLBeginStateChangeImpl(MwLL handle) { MwLLShow(handle, 0); } diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index e07eb64..85b8b5b 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1146,6 +1146,10 @@ static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { rect->height = [screen frame].size.height; } +static void MwLLSetupDragAndDropImpl(MwLL handle) { + (void)handle; +} + static void MwLLBeginStateChangeImpl(MwLL handle) { MwLLShow(handle, 0); } diff --git a/src/backend/gdi.c b/src/backend/gdi.c index acc341e..dbd87ac 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -1,5 +1,7 @@ #include +#include "../../external/stb_ds.h" + typedef struct userdata { MwLL ll; POINT min; @@ -10,8 +12,26 @@ typedef struct userdata { static struct symtbl { void* lib_dwmapi; + void* shell32lib; + void* ole32lib; + void* urlmonlib; + MwBool has_drag_and_drop; HRESULT(WINAPI* DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); + UINT(WINAPI* DragQueryFileW)(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch); + UINT(WINAPI* DragQueryFileA)(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch); + void(WINAPI* ReleaseStgMedium)(LPSTGMEDIUM unnamedParam1); + HRESULT(WINAPI* OleInitialize)(LPVOID pvReserved); + HRESULT(WINAPI* RegisterDragDrop)(HWND hwnd, LPDROPTARGET pDropTarget); + HRESULT(WINAPI* FindMimeFromData)( + LPBC pBC, + LPCWSTR pwzUrl, + LPVOID pBuffer, + DWORD cbSize, + LPCWSTR pwzMimeProposed, + DWORD dwMimeFlags, + LPWSTR* ppwzMimeOut, + DWORD dwReserved); } wsymtbl; static int is_plgblt_reliable = 0; @@ -420,6 +440,9 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { SetWindowPos(r->gdi.hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + r->gdi.dropTarget = NULL; + r->gdi.drag_update = MwFALSE; + return r; } @@ -434,6 +457,8 @@ static void MwLLDestroyImpl(MwLL handle) { if(handle->gdi.cursor != NULL) DestroyCursor(handle->gdi.cursor); + if(handle->gdi.dropTarget) free(handle->gdi.dropTarget); + free(handle); } @@ -547,7 +572,7 @@ static int MwLLPendingImpl(MwLL handle) { (void)handle; - if(handle->gdi.get_clipboard || handle->gdi.get_darktheme) return 1; + if(handle->gdi.get_clipboard || handle->gdi.get_darktheme || handle->gdi.drag_update) return 1; return PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE) ? 1 : 0; } @@ -579,8 +604,7 @@ static void MwLLNextEventImpl(MwLL handle) { handle->gdi.get_darktheme = 0; } - while(PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE)) { - GetMessage(&msg, handle->gdi.hWnd, 0, 0); + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } @@ -994,8 +1018,134 @@ static void MwLLClipImpl(MwLL handle, MwRect* rect) { } } +static HRESULT STDMETHODCALLTYPE GDIDT_QueryInterface(IDropTarget* this_, REFIID riid, void** ppv) { + if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDropTarget)) { + *ppv = this_; + this_->lpVtbl->AddRef(this_); + return S_OK; + } + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE GDIDT_AddRef(IDropTarget* this_) { + MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; + return InterlockedIncrement(&self->refCount); +} + +static ULONG STDMETHODCALLTYPE GDIDT_Release(IDropTarget* this_) { + MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; + LONG c = InterlockedDecrement(&self->refCount); + if(c == 0) free(self); + return c; +} + +static HRESULT STDMETHODCALLTYPE GDIDT_DragEnter(IDropTarget* this_, IDataObject* pDataObj, + DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { + *pdwEffect = DROPEFFECT_COPY; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE GDIDT_DragOver(IDropTarget* this_, DWORD grfKeyState, + POINTL pt, DWORD* pdwEffect) { + MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; + self->handle->gdi.drag_update = MwTRUE; + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE GDIDT_DragLeave(IDropTarget* this_) { + MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; + self->handle->gdi.drag_update = MwFALSE; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE GDIDT_Drop(IDropTarget* this_, IDataObject* pDataObj, + DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { + FORMATETC fmt = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + STGMEDIUM stg; + MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; + + self->handle->gdi.drag_update = MwTRUE; + + if(pDataObj->lpVtbl->GetData(pDataObj, &fmt, &stg) == S_OK) { + HDROP hDrop = (HDROP)stg.hGlobal; + UINT count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); + UINT i, n; + HRESULT hr; + + for(i = 0; i < count; i++) { + wchar_t path[MAX_PATH]; + char path_normal[MAX_PATH]; + char* mime_type_normal; + wchar_t* mime_type = NULL; + int mime_type_size; + HRESULT hr; + int i; + + wsymtbl.DragQueryFileW(hDrop, i, path, MAX_PATH); + wsymtbl.DragQueryFileA(hDrop, i, path_normal, MAX_PATH); + hr = wsymtbl.FindMimeFromData(NULL, path, NULL, 0, + NULL, FMFD_DEFAULT, &mime_type, 0x0); + + mime_type_size = WideCharToMultiByte(CP_ACP, 0, mime_type, -1, NULL, 0, NULL, FALSE); + mime_type_normal = malloc(sizeof(mime_type_size)); + WideCharToMultiByte(CP_ACP, 0, mime_type, -1, mime_type_normal, mime_type_size, NULL, FALSE); + + if(mime_type_size == 0) { + printf("Error converting mime type to multi-byte: %ld\n", GetLastError()); + } else { + if(self->handle->common.known_mime_types) { + for(n = 0; n < arrlen(self->handle->common.known_mime_types); n++) { + if(strcmp(mime_type_normal, self->handle->common.known_mime_types[n]) == 0) { + MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal); + break; + } + } + } else { + MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal); + } + } + free(mime_type); + } + + wsymtbl.ReleaseStgMedium(&stg); + *pdwEffect = DROPEFFECT_COPY; + } else { + *pdwEffect = DROPEFFECT_NONE; + } + return S_OK; +} + +static IDropTargetVtbl DropTarget_Vtbl = { + GDIDT_QueryInterface, + GDIDT_AddRef, + GDIDT_Release, + GDIDT_DragEnter, + GDIDT_DragOver, + GDIDT_DragLeave, + GDIDT_Drop}; + +static void MwLLSetupDragAndDropImpl(MwLL handle) { + HRESULT hr = 0; + + handle->gdi.dropTarget = (MwLLGDIDropTarget*)malloc(sizeof(MwLLGDIDropTarget)); + handle->gdi.dropTarget->lpVtbl = &DropTarget_Vtbl; + handle->gdi.dropTarget->refCount = 1; + handle->gdi.dropTarget->hwnd = handle->gdi.hWnd; + handle->gdi.dropTarget->handle = handle; + + hr = wsymtbl.RegisterDragDrop(handle->gdi.hWnd, (IDropTarget*)handle->gdi.dropTarget); + if(!SUCCEEDED(hr)) { + printf("RegisterDragDrop failed; %08lx\n", hr); + return; + } + printf("dnd setup\n"); +} + static int MwLLGDICallInitImpl(void) { - void* ntdll; + void* ntdll; + HRESULT hr; memset(&wsymtbl, 0, sizeof(wsymtbl)); @@ -1009,6 +1159,69 @@ static int MwLLGDICallInitImpl(void) { is_plgblt_reliable = 1; } + wsymtbl.has_drag_and_drop = MwFALSE; + + /* Drag and Drop initialization */ + { + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + /* The only other error - COM already being initialized - can be ignored */ + if(hr == RPC_E_CHANGED_MODE) { + goto no_dnd; + } + if(!SUCCEEDED(hr) && hr != S_FALSE) { + printf("CoInitialize error: %08lx\n", hr); + goto dnd_error; + } + hr = OleInitialize(NULL); + if(!SUCCEEDED(hr)) { + if(hr == RPC_E_CHANGED_MODE) { + no_dnd: + printf("Cannot do drag and drop; Microsoft hates you and if you use COM anywhere else it has to be apartment threaded.\n"); + goto dnd_error; + } else { + printf("OleInitialize failed; %08lx. Drag and Drop won't be supported.\n", hr); + goto dnd_error; + } + } + + wsymtbl.has_drag_and_drop = MwTRUE; + + if(!(wsymtbl.shell32lib = LoadLibrary("shell32.dll"))) { + goto dnd_error; + }; + if(!(wsymtbl.ole32lib = LoadLibrary("ole32.dll"))) { + goto dnd_error; + }; + if(!(wsymtbl.urlmonlib = LoadLibrary("Urlmon.dll"))) { + goto dnd_error; + }; + +#define SHELL32_FUNC(x) \ + if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.shell32lib, #x))) { \ + printf(#x "not found, drag and drop will not be supported"); \ + goto dnd_error; \ + } +#define OLE32_FUNC(x) \ + if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.ole32lib, #x))) { \ + printf(#x "not found, drag and drop will not be supported"); \ + goto dnd_error; \ + } +#define URLMON_FUNC(x) \ + if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.urlmonlib, #x))) { \ + printf(#x "not found, drag and drop will not be supported"); \ + goto dnd_error; \ + } + + SHELL32_FUNC(DragQueryFileW); + SHELL32_FUNC(DragQueryFileA); + OLE32_FUNC(ReleaseStgMedium); + OLE32_FUNC(RegisterDragDrop); + URLMON_FUNC(FindMimeFromData); + + wsymtbl.has_drag_and_drop = MwTRUE; + } +dnd_error: + /* TODO: check properly */ return 0; } diff --git a/src/backend/haiku.cc b/src/backend/haiku.cc index 8c4f8bf..2c796d6 100644 --- a/src/backend/haiku.cc +++ b/src/backend/haiku.cc @@ -879,6 +879,10 @@ static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { delete screen; } +static void MwLLSetupDragAndDropImpl(MwLL handle) { + (void)handle; +} + static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { (void)handle; (void)toggle; diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 48d6c76..839e9ac 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1779,6 +1779,10 @@ static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { rect->height = handle->wayland.mh; } +static void MwLLSetupDragAndDropImpl(MwLL handle) { + (void)handle; +} + static void MwLLBeginStateChangeImpl(MwLL handle) { (void)handle; /* no-op */ diff --git a/src/backend/x11.c b/src/backend/x11.c index 79ce429..cc4d22b 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -1361,6 +1361,10 @@ static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { rect->height = xwa.height; } +static void MwLLSetupDragAndDropImpl(MwLL handle) { + (void)handle; +} + static void MwLLBeginStateChangeImpl(MwLL handle) { MwLLShow(handle, 0); } diff --git a/src/core.c b/src/core.c index 7059840..2eca665 100644 --- a/src/core.c +++ b/src/core.c @@ -658,6 +658,10 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { if(h->lowlevel != NULL) MwLLSetDarkTheme(h->lowlevel, n); } + + if(strcmp(key, MwNacceptsDnD) == 0) { + if(handle->lowlevel != NULL) MwLLSetupDragAndDrop(handle->lowlevel); + } } void MwSetText(MwWidget handle, const char* key, const char* value) { @@ -692,6 +696,12 @@ void MwSetText(MwWidget handle, const char* key, const char* value) { if(strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0) { MwForceRender(handle); } + + if(strcmp(key, MwNacceptedMimeType) == 0) { + if(handle->lowlevel != NULL) { + arrput(handle->lowlevel->common.known_mime_types, value); + } + } } void MwSetVoid(MwWidget handle, const char* key, void* value) { diff --git a/src/lowlevel.c b/src/lowlevel.c index bc9e55b..aca10c2 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -50,8 +50,8 @@ void (*MwLLGetClipboard)(MwLL, int clipboard_type) = NULL; void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point) = NULL; void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect) = NULL; - -void (*MwLLSetDarkTheme)(MwLL handle, int toggle) = NULL; +void (*MwLLSetupDragAndDrop)(MwLL handle) = NULL; +void (*MwLLSetDarkTheme)(MwLL handle, int toggle) = NULL; MwBool (*MwLLDoModern)(MwLL handle) = NULL; @@ -64,6 +64,7 @@ void MwLLCreateCommon(MwLL handle) { memset(handle->common.handler, 0, sizeof(*handle->common.handler)); handle->common.supports_transparency = 0; + handle->common.known_mime_types = NULL; } void MwLLDestroyCommon(MwLL handle) { diff --git a/src/widget/entry.c b/src/widget/entry.c index 65cd903..dd867d7 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -9,6 +9,7 @@ static int wcreate(MwWidget handle) { t->right = 0; t->length = 0; t->cursor_blink_timer = 0; + t->active = 0; handle->internal = t; while(topmost_parent->parent) topmost_parent = topmost_parent->parent; @@ -40,7 +41,7 @@ static void tick(MwWidget handle) { if(++t->cursor_blink_timer >= 30) { t->cursor_blink_timer = 0; } - MwDispatch(handle, draw); + MwForceRender(handle); } } static void draw(MwWidget handle) { @@ -185,7 +186,7 @@ static void mouse_down(MwWidget handle, void* ptr) { MwEntry t = topmost_parent->monitored_entries[i]->internal; t->active = MwFALSE; t->cursor_blink_timer = 0; - MwDispatch(topmost_parent->monitored_entries[i], draw); + MwForceRender(topmost_parent->monitored_entries[i]); } t->active = MwTRUE; MwForceRender2(handle, NULL); From 27b4f8384078bd63295a08e4be2fcc3a40937e46 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 22 Jul 2026 19:49:05 -0700 Subject: [PATCH 003/168] linke to ole32 --- CMakeLists.txt | 2 +- NTMakefile | 2 +- WatMakefile | 2 +- pl/ostype/Windows.pl | 1 + tools/genmk.pl | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b9e90d0..39f26d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -329,7 +329,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_SYSTEM_NAME STREQUAL "MSYS") PRIVATE USE_GDI ) - list(APPEND LIBRARIES gdi32 winmm) + list(APPEND LIBRARIES gdi32 ole32 winmm) target_link_options( Mw PRIVATE diff --git a/NTMakefile b/NTMakefile index a3fc76a..8afa320 100644 --- a/NTMakefile +++ b/NTMakefile @@ -321,7 +321,7 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib winmm.lib user32.lib advapi32.lib + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib winmm.lib ole32.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index afeb560..c2af03e 100644 --- a/WatMakefile +++ b/WatMakefile @@ -320,7 +320,7 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/checkbox.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library winmm.lib library user32.lib library advapi32.lib + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library winmm.lib library ole32.lib library user32.lib library advapi32.lib diff --git a/pl/ostype/Windows.pl b/pl/ostype/Windows.pl index f79469f..af9486c 100644 --- a/pl/ostype/Windows.pl +++ b/pl/ostype/Windows.pl @@ -5,5 +5,6 @@ $math = ""; add_ldflags("-Wl,--out-implib,src/libMw.dll.a -static-libgcc"); use_backend("gdi"); add_libs("-lwinmm"); +add_libs("-lole32"); 1; diff --git a/tools/genmk.pl b/tools/genmk.pl index 9903c11..2c68608 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -190,7 +190,7 @@ sub generate { print(OUT "src${dir}Mw.dll: " . cobjs($dir) . "\n"); print( OUT " \$(LD) \$(MW_LDFLAGS) $c_dllout $dllout\$@ " . cobjs($dir, $prefobj) - . " $needlibs ${lib}opengl32.lib ${lib}gdi32.lib ${lib}winmm.lib ${lib}user32.lib ${lib}advapi32.lib\n" + . " $needlibs ${lib}opengl32.lib ${lib}gdi32.lib ${lib}winmm.lib ${lib}ole32.lib ${lib}user32.lib ${lib}advapi32.lib\n" ); print(OUT " $c_dllafter\n"); print(OUT "\n"); From b3e24df2f677c9b642119552b812f2b1c0eff916 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 22 Jul 2026 19:51:11 -0700 Subject: [PATCH 004/168] include urlmon.h in MachDep.h --- include/Mw/MachDep.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 4c98b24..5433c7e 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -26,6 +26,7 @@ #ifdef _MILSKO #include #include +#include #ifndef GWLP_USERDATA #define GWLP_USERDATA GWL_USERDATA #define GWLP_WNDPROC GWL_WNDPROC From 981591120c5f3e66beadc8dede29760272c659d6 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 22 Jul 2026 19:54:27 -0700 Subject: [PATCH 005/168] linke to uuid --- CMakeLists.txt | 2 +- pl/ostype/Windows.pl | 1 + tools/genmk.pl | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 39f26d0..e7aefde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -329,7 +329,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_SYSTEM_NAME STREQUAL "MSYS") PRIVATE USE_GDI ) - list(APPEND LIBRARIES gdi32 ole32 winmm) + list(APPEND LIBRARIES gdi32 ole32 winmm uuid) target_link_options( Mw PRIVATE diff --git a/pl/ostype/Windows.pl b/pl/ostype/Windows.pl index af9486c..9a066d8 100644 --- a/pl/ostype/Windows.pl +++ b/pl/ostype/Windows.pl @@ -6,5 +6,6 @@ add_ldflags("-Wl,--out-implib,src/libMw.dll.a -static-libgcc"); use_backend("gdi"); add_libs("-lwinmm"); add_libs("-lole32"); +add_libs("-luuid"); 1; diff --git a/tools/genmk.pl b/tools/genmk.pl index 2c68608..8362bd3 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -190,7 +190,7 @@ sub generate { print(OUT "src${dir}Mw.dll: " . cobjs($dir) . "\n"); print( OUT " \$(LD) \$(MW_LDFLAGS) $c_dllout $dllout\$@ " . cobjs($dir, $prefobj) - . " $needlibs ${lib}opengl32.lib ${lib}gdi32.lib ${lib}winmm.lib ${lib}ole32.lib ${lib}user32.lib ${lib}advapi32.lib\n" + . " $needlibs ${lib}opengl32.lib ${lib}gdi32.lib ${lib}winmm.lib ${lib}ole32.lib ${lib}uuid.lib ${lib}user32.lib ${lib}advapi32.lib\n" ); print(OUT " $c_dllafter\n"); print(OUT "\n"); From fb6c7a47729b364b585569495a8c4b8e30ae3d7f Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 22 Jul 2026 19:55:40 -0700 Subject: [PATCH 006/168] replace FMFD_DEFAULT with 0 --- include/Mw/MachDep.h | 1 - src/backend/gdi.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 5433c7e..4c98b24 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -26,7 +26,6 @@ #ifdef _MILSKO #include #include -#include #ifndef GWLP_USERDATA #define GWLP_USERDATA GWL_USERDATA #define GWLP_WNDPROC GWL_WNDPROC diff --git a/src/backend/gdi.c b/src/backend/gdi.c index dbd87ac..e08d4e1 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -1086,7 +1086,7 @@ static HRESULT STDMETHODCALLTYPE GDIDT_Drop(IDropTarget* this_, IDataObject* pDa wsymtbl.DragQueryFileW(hDrop, i, path, MAX_PATH); wsymtbl.DragQueryFileA(hDrop, i, path_normal, MAX_PATH); hr = wsymtbl.FindMimeFromData(NULL, path, NULL, 0, - NULL, FMFD_DEFAULT, &mime_type, 0x0); + NULL, 0, &mime_type, 0x0); mime_type_size = WideCharToMultiByte(CP_ACP, 0, mime_type, -1, NULL, 0, NULL, FALSE); mime_type_normal = malloc(sizeof(mime_type_size)); From 0fd0611a993abf47413a590eb713bbf76220274b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 22 Jul 2026 20:02:01 -0700 Subject: [PATCH 007/168] dynload CoInitializeEx --- src/backend/gdi.c | 48 ++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index e08d4e1..078c174 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -32,6 +32,9 @@ static struct symtbl { DWORD dwMimeFlags, LPWSTR* ppwzMimeOut, DWORD dwReserved); + HRESULT (*CoInitializeEx)( + LPVOID pvReserved, + DWORD dwCoInit); } wsymtbl; static int is_plgblt_reliable = 0; @@ -1163,29 +1166,6 @@ static int MwLLGDICallInitImpl(void) { /* Drag and Drop initialization */ { - hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - /* The only other error - COM already being initialized - can be ignored */ - if(hr == RPC_E_CHANGED_MODE) { - goto no_dnd; - } - if(!SUCCEEDED(hr) && hr != S_FALSE) { - printf("CoInitialize error: %08lx\n", hr); - goto dnd_error; - } - hr = OleInitialize(NULL); - if(!SUCCEEDED(hr)) { - if(hr == RPC_E_CHANGED_MODE) { - no_dnd: - printf("Cannot do drag and drop; Microsoft hates you and if you use COM anywhere else it has to be apartment threaded.\n"); - goto dnd_error; - } else { - printf("OleInitialize failed; %08lx. Drag and Drop won't be supported.\n", hr); - goto dnd_error; - } - } - - wsymtbl.has_drag_and_drop = MwTRUE; - if(!(wsymtbl.shell32lib = LoadLibrary("shell32.dll"))) { goto dnd_error; }; @@ -1216,8 +1196,30 @@ static int MwLLGDICallInitImpl(void) { SHELL32_FUNC(DragQueryFileA); OLE32_FUNC(ReleaseStgMedium); OLE32_FUNC(RegisterDragDrop); + OLE32_FUNC(CoInitializeEx); URLMON_FUNC(FindMimeFromData); + hr = wsymtbl.CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + /* The only other error - COM already being initialized - can be ignored */ + if(hr == RPC_E_CHANGED_MODE) { + goto no_dnd; + } + if(!SUCCEEDED(hr) && hr != S_FALSE) { + printf("CoInitialize error: %08lx\n", hr); + goto dnd_error; + } + hr = OleInitialize(NULL); + if(!SUCCEEDED(hr)) { + if(hr == RPC_E_CHANGED_MODE) { + no_dnd: + printf("Cannot do drag and drop; Microsoft hates you and if you use COM anywhere else it has to be apartment threaded.\n"); + goto dnd_error; + } else { + printf("OleInitialize failed; %08lx. Drag and Drop won't be supported.\n", hr); + goto dnd_error; + } + } + wsymtbl.has_drag_and_drop = MwTRUE; } dnd_error: From 7e339cfd60bd2d7d274cc78675cf5416f85ae141 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 22 Jul 2026 21:31:03 -0700 Subject: [PATCH 008/168] gdi: properly quit drag and drop after its finished --- include/Mw/LowLevel/GDI.h | 1 + src/backend/gdi.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/Mw/LowLevel/GDI.h b/include/Mw/LowLevel/GDI.h index 6230a36..581c32d 100644 --- a/include/Mw/LowLevel/GDI.h +++ b/include/Mw/LowLevel/GDI.h @@ -34,6 +34,7 @@ struct _MwLLGDI { struct _MwLLGDIDropTarget* dropTarget; struct _MwLLGDIDropSource* dropSource; MwBool drag_update; + MwBool finishing_drag; }; struct _MwLLGDIColor { diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 078c174..6e0383b 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -607,6 +607,10 @@ static void MwLLNextEventImpl(MwLL handle) { handle->gdi.get_darktheme = 0; } + if(handle->gdi.finishing_drag) { + handle->gdi.drag_update = 0; + handle->gdi.finishing_drag = 0; + } while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -1102,11 +1106,12 @@ static HRESULT STDMETHODCALLTYPE GDIDT_Drop(IDropTarget* this_, IDataObject* pDa for(n = 0; n < arrlen(self->handle->common.known_mime_types); n++) { if(strcmp(mime_type_normal, self->handle->common.known_mime_types[n]) == 0) { MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal); - break; + self->handle->gdi.finishing_drag = 1; } } } else { MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal); + self->handle->gdi.finishing_drag = 1; } } free(mime_type); From c404e9e14b05d1c4285635f4e1266c6e3ca9b3e7 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 22 Jul 2026 21:33:37 -0700 Subject: [PATCH 009/168] remove some leftover debug prints oops --- src/backend/gdi.c | 1 - src/text/gdi.c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 6e0383b..37bb9c5 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -1148,7 +1148,6 @@ static void MwLLSetupDragAndDropImpl(MwLL handle) { printf("RegisterDragDrop failed; %08lx\n", hr); return; } - printf("dnd setup\n"); } static int MwLLGDICallInitImpl(void) { diff --git a/src/text/gdi.c b/src/text/gdi.c index ab54664..b5f3ced 100644 --- a/src/text/gdi.c +++ b/src/text/gdi.c @@ -215,7 +215,6 @@ static HANDLE WINAPI _AddFontMemResourceExPolyFill(PVOID pFileView, DWORD cjSize OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL); - printf("%d\n", tempFile); if(tempFile != INVALID_HANDLE_VALUE) { goto success; } else { From f35e7817624f93b6512cd0b0cc9a8443377857df Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 23 Jul 2026 00:10:26 -0700 Subject: [PATCH 010/168] win32: move away from com for drag and drop to avoid conflicts (and because com sucks) --- include/Mw/LowLevel/GDI.h | 14 --- src/backend/gdi.c | 188 +++++++++++--------------------------- 2 files changed, 53 insertions(+), 149 deletions(-) diff --git a/include/Mw/LowLevel/GDI.h b/include/Mw/LowLevel/GDI.h index 581c32d..e505b0a 100644 --- a/include/Mw/LowLevel/GDI.h +++ b/include/Mw/LowLevel/GDI.h @@ -29,12 +29,6 @@ struct _MwLLGDI { int force_render; int get_clipboard; int get_darktheme; - - /* drag and drop */ - struct _MwLLGDIDropTarget* dropTarget; - struct _MwLLGDIDropSource* dropSource; - MwBool drag_update; - MwBool finishing_drag; }; struct _MwLLGDIColor { @@ -53,14 +47,6 @@ struct _MwLLGDIPixmap { HBITMAP hMask2; }; -struct _MwLLGDIDropTarget{ - struct IDropTargetVtbl *lpVtbl; - LONG refCount; - HWND hwnd; - MwLL handle; -}; -typedef struct _MwLLGDIDropTarget MwLLGDIDropTarget; - MWDECL int MwLLGDICallInit(void); MWDECL HCURSOR MwLLGDICreateCursor(MwCursor* image, MwCursor* mask); diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 37bb9c5..849f8af 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -91,6 +91,8 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { if(u == NULL) return DefWindowProc(hWnd, msg, wp, lp); switch(msg) { + case WM_INITDIALOG: + return TRUE; case WM_PAINT: { PAINTSTRUCT ps; @@ -181,6 +183,49 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { MwLLDispatch(u->ll, up, &p); break; } + case WM_DROPFILES: { + HDROP hDrop = (HDROP)wp; + UINT count; + UINT i, n; + HRESULT hr; + + count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); + + for(i = 0; i < count; i++) { + wchar_t path[MAX_PATH]; + char path_normal[MAX_PATH]; + char* mime_type_normal; + wchar_t* mime_type = NULL; + int mime_type_size; + HRESULT hr; + int i; + + wsymtbl.DragQueryFileW(hDrop, i, path, MAX_PATH); + wsymtbl.DragQueryFileA(hDrop, i, path_normal, MAX_PATH); + hr = wsymtbl.FindMimeFromData(NULL, path, NULL, 0, + NULL, 0, &mime_type, 0x0); + + mime_type_size = WideCharToMultiByte(CP_ACP, 0, mime_type, -1, NULL, 0, NULL, FALSE); + mime_type_normal = malloc(sizeof(mime_type_size)); + WideCharToMultiByte(CP_ACP, 0, mime_type, -1, mime_type_normal, mime_type_size, NULL, FALSE); + + if(mime_type_size == 0) { + printf("Error converting mime type to multi-byte: %ld\n", GetLastError()); + } else { + if(u->ll->common.known_mime_types) { + for(n = 0; n < arrlen(u->ll->common.known_mime_types); n++) { + if(strcmp(mime_type_normal, u->ll->common.known_mime_types[n]) == 0) { + MwDispatchUserHandler(u->ll->common.user, MwNdragAndDropHandler, path_normal); + } + } + } else { + MwDispatchUserHandler(u->ll->common.user, MwNdragAndDropHandler, path_normal); + } + } + } + DragFinish(hDrop); + break; + } case WM_MOUSEMOVE: { MwPoint p; @@ -210,6 +255,7 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { SetCursorPos(p.x, p.y); } + break; } case WM_SIZE: @@ -443,9 +489,6 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { SetWindowPos(r->gdi.hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - r->gdi.dropTarget = NULL; - r->gdi.drag_update = MwFALSE; - return r; } @@ -460,8 +503,6 @@ static void MwLLDestroyImpl(MwLL handle) { if(handle->gdi.cursor != NULL) DestroyCursor(handle->gdi.cursor); - if(handle->gdi.dropTarget) free(handle->gdi.dropTarget); - free(handle); } @@ -575,7 +616,7 @@ static int MwLLPendingImpl(MwLL handle) { (void)handle; - if(handle->gdi.get_clipboard || handle->gdi.get_darktheme || handle->gdi.drag_update) return 1; + if(handle->gdi.get_clipboard || handle->gdi.get_darktheme) return 1; return PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE) ? 1 : 0; } @@ -607,13 +648,11 @@ static void MwLLNextEventImpl(MwLL handle) { handle->gdi.get_darktheme = 0; } - if(handle->gdi.finishing_drag) { - handle->gdi.drag_update = 0; - handle->gdi.finishing_drag = 0; - } - while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { + if(GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } } @@ -1025,129 +1064,8 @@ static void MwLLClipImpl(MwLL handle, MwRect* rect) { } } -static HRESULT STDMETHODCALLTYPE GDIDT_QueryInterface(IDropTarget* this_, REFIID riid, void** ppv) { - if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDropTarget)) { - *ppv = this_; - this_->lpVtbl->AddRef(this_); - return S_OK; - } - *ppv = NULL; - return E_NOINTERFACE; -} - -static ULONG STDMETHODCALLTYPE GDIDT_AddRef(IDropTarget* this_) { - MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; - return InterlockedIncrement(&self->refCount); -} - -static ULONG STDMETHODCALLTYPE GDIDT_Release(IDropTarget* this_) { - MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; - LONG c = InterlockedDecrement(&self->refCount); - if(c == 0) free(self); - return c; -} - -static HRESULT STDMETHODCALLTYPE GDIDT_DragEnter(IDropTarget* this_, IDataObject* pDataObj, - DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { - *pdwEffect = DROPEFFECT_COPY; - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE GDIDT_DragOver(IDropTarget* this_, DWORD grfKeyState, - POINTL pt, DWORD* pdwEffect) { - MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; - self->handle->gdi.drag_update = MwTRUE; - - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE GDIDT_DragLeave(IDropTarget* this_) { - MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; - self->handle->gdi.drag_update = MwFALSE; - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE GDIDT_Drop(IDropTarget* this_, IDataObject* pDataObj, - DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { - FORMATETC fmt = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; - STGMEDIUM stg; - MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_; - - self->handle->gdi.drag_update = MwTRUE; - - if(pDataObj->lpVtbl->GetData(pDataObj, &fmt, &stg) == S_OK) { - HDROP hDrop = (HDROP)stg.hGlobal; - UINT count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); - UINT i, n; - HRESULT hr; - - for(i = 0; i < count; i++) { - wchar_t path[MAX_PATH]; - char path_normal[MAX_PATH]; - char* mime_type_normal; - wchar_t* mime_type = NULL; - int mime_type_size; - HRESULT hr; - int i; - - wsymtbl.DragQueryFileW(hDrop, i, path, MAX_PATH); - wsymtbl.DragQueryFileA(hDrop, i, path_normal, MAX_PATH); - hr = wsymtbl.FindMimeFromData(NULL, path, NULL, 0, - NULL, 0, &mime_type, 0x0); - - mime_type_size = WideCharToMultiByte(CP_ACP, 0, mime_type, -1, NULL, 0, NULL, FALSE); - mime_type_normal = malloc(sizeof(mime_type_size)); - WideCharToMultiByte(CP_ACP, 0, mime_type, -1, mime_type_normal, mime_type_size, NULL, FALSE); - - if(mime_type_size == 0) { - printf("Error converting mime type to multi-byte: %ld\n", GetLastError()); - } else { - if(self->handle->common.known_mime_types) { - for(n = 0; n < arrlen(self->handle->common.known_mime_types); n++) { - if(strcmp(mime_type_normal, self->handle->common.known_mime_types[n]) == 0) { - MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal); - self->handle->gdi.finishing_drag = 1; - } - } - } else { - MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal); - self->handle->gdi.finishing_drag = 1; - } - } - free(mime_type); - } - - wsymtbl.ReleaseStgMedium(&stg); - *pdwEffect = DROPEFFECT_COPY; - } else { - *pdwEffect = DROPEFFECT_NONE; - } - return S_OK; -} - -static IDropTargetVtbl DropTarget_Vtbl = { - GDIDT_QueryInterface, - GDIDT_AddRef, - GDIDT_Release, - GDIDT_DragEnter, - GDIDT_DragOver, - GDIDT_DragLeave, - GDIDT_Drop}; - static void MwLLSetupDragAndDropImpl(MwLL handle) { - HRESULT hr = 0; - - handle->gdi.dropTarget = (MwLLGDIDropTarget*)malloc(sizeof(MwLLGDIDropTarget)); - handle->gdi.dropTarget->lpVtbl = &DropTarget_Vtbl; - handle->gdi.dropTarget->refCount = 1; - handle->gdi.dropTarget->hwnd = handle->gdi.hWnd; - handle->gdi.dropTarget->handle = handle; - - hr = wsymtbl.RegisterDragDrop(handle->gdi.hWnd, (IDropTarget*)handle->gdi.dropTarget); - if(!SUCCEEDED(hr)) { - printf("RegisterDragDrop failed; %08lx\n", hr); - return; - } + DragAcceptFiles(handle->gdi.hWnd, TRUE); } static int MwLLGDICallInitImpl(void) { From 9dd96d9cecaa94f2b3b9801a4bf09b8b7b6c45fc Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 23 Jul 2026 00:34:38 -0700 Subject: [PATCH 011/168] dynload drag functions --- include/Mw/LowLevel.h | 1 + src/backend/gdi.c | 52 ++++++++----------------------------------- src/core.c | 11 +++++++++ 3 files changed, 21 insertions(+), 43 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index b58d54e..6089e48 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -206,6 +206,7 @@ struct _MwLLHandler { void (*focus_out)(MwLL handle, void* data); void (*clipboard)(MwLL handle, void* data); void (*dark_theme)(MwLL handle, void* data); + void (*drag_and_drop)(MwLL handle, void* data); }; struct _MwLLTextDispatchTable { diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 849f8af..e9f3d4c 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -13,16 +13,13 @@ typedef struct userdata { static struct symtbl { void* lib_dwmapi; void* shell32lib; - void* ole32lib; void* urlmonlib; MwBool has_drag_and_drop; HRESULT(WINAPI* DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); + UINT(WINAPI* DragQueryFileW)(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch); UINT(WINAPI* DragQueryFileA)(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch); - void(WINAPI* ReleaseStgMedium)(LPSTGMEDIUM unnamedParam1); - HRESULT(WINAPI* OleInitialize)(LPVOID pvReserved); - HRESULT(WINAPI* RegisterDragDrop)(HWND hwnd, LPDROPTARGET pDropTarget); HRESULT(WINAPI* FindMimeFromData)( LPBC pBC, LPCWSTR pwzUrl, @@ -32,9 +29,8 @@ static struct symtbl { DWORD dwMimeFlags, LPWSTR* ppwzMimeOut, DWORD dwReserved); - HRESULT (*CoInitializeEx)( - LPVOID pvReserved, - DWORD dwCoInit); + void (*DragAcceptFiles)(HWND hWnd, BOOL fAccept); + void (*DragFinish)(HDROP hDrop); } wsymtbl; static int is_plgblt_reliable = 0; @@ -215,15 +211,15 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { if(u->ll->common.known_mime_types) { for(n = 0; n < arrlen(u->ll->common.known_mime_types); n++) { if(strcmp(mime_type_normal, u->ll->common.known_mime_types[n]) == 0) { - MwDispatchUserHandler(u->ll->common.user, MwNdragAndDropHandler, path_normal); + MwLLDispatch(u->ll, drag_and_drop, path_normal); } } } else { - MwDispatchUserHandler(u->ll->common.user, MwNdragAndDropHandler, path_normal); + MwLLDispatch(u->ll, drag_and_drop, path_normal); } } } - DragFinish(hDrop); + wsymtbl.DragFinish(hDrop); break; } case WM_MOUSEMOVE: @@ -1065,7 +1061,7 @@ static void MwLLClipImpl(MwLL handle, MwRect* rect) { } static void MwLLSetupDragAndDropImpl(MwLL handle) { - DragAcceptFiles(handle->gdi.hWnd, TRUE); + wsymtbl.DragAcceptFiles(handle->gdi.hWnd, TRUE); } static int MwLLGDICallInitImpl(void) { @@ -1091,9 +1087,6 @@ static int MwLLGDICallInitImpl(void) { if(!(wsymtbl.shell32lib = LoadLibrary("shell32.dll"))) { goto dnd_error; }; - if(!(wsymtbl.ole32lib = LoadLibrary("ole32.dll"))) { - goto dnd_error; - }; if(!(wsymtbl.urlmonlib = LoadLibrary("Urlmon.dll"))) { goto dnd_error; }; @@ -1103,11 +1096,6 @@ static int MwLLGDICallInitImpl(void) { printf(#x "not found, drag and drop will not be supported"); \ goto dnd_error; \ } -#define OLE32_FUNC(x) \ - if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.ole32lib, #x))) { \ - printf(#x "not found, drag and drop will not be supported"); \ - goto dnd_error; \ - } #define URLMON_FUNC(x) \ if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.urlmonlib, #x))) { \ printf(#x "not found, drag and drop will not be supported"); \ @@ -1116,32 +1104,10 @@ static int MwLLGDICallInitImpl(void) { SHELL32_FUNC(DragQueryFileW); SHELL32_FUNC(DragQueryFileA); - OLE32_FUNC(ReleaseStgMedium); - OLE32_FUNC(RegisterDragDrop); - OLE32_FUNC(CoInitializeEx); + SHELL32_FUNC(DragAcceptFiles); + SHELL32_FUNC(DragFinish); URLMON_FUNC(FindMimeFromData); - hr = wsymtbl.CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - /* The only other error - COM already being initialized - can be ignored */ - if(hr == RPC_E_CHANGED_MODE) { - goto no_dnd; - } - if(!SUCCEEDED(hr) && hr != S_FALSE) { - printf("CoInitialize error: %08lx\n", hr); - goto dnd_error; - } - hr = OleInitialize(NULL); - if(!SUCCEEDED(hr)) { - if(hr == RPC_E_CHANGED_MODE) { - no_dnd: - printf("Cannot do drag and drop; Microsoft hates you and if you use COM anywhere else it has to be apartment threaded.\n"); - goto dnd_error; - } else { - printf("OleInitialize failed; %08lx. Drag and Drop won't be supported.\n", hr); - goto dnd_error; - } - } - wsymtbl.has_drag_and_drop = MwTRUE; } dnd_error: diff --git a/src/core.c b/src/core.c index 2eca665..d1a5d9b 100644 --- a/src/core.c +++ b/src/core.c @@ -192,6 +192,16 @@ static void llclipboardhandler(MwLL handle, void* data) { MwDispatchUserHandler(h, MwNclipboardHandler, data); } +static void lldraganddrophandler(MwLL handle, void* data) { + MwWidget h = (MwWidget)handle->common.user; + const char * p = data; + if(MwGetInteger(h, MwNdisabled) == 1) return; + + printf("%s\n",p); + MwDispatchUserHandler(h, MwNdragAndDropHandler, data); +} + + /* if both of them are true * 1. widget class is not NULL * 2. parent is NULL @@ -285,6 +295,7 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, h->lowlevel->common.handler->focus_out = llfocusouthandler; h->lowlevel->common.handler->clipboard = llclipboardhandler; h->lowlevel->common.handler->dark_theme = lldarkthemehandler; + h->lowlevel->common.handler->drag_and_drop = lldraganddrophandler; } if(parent != NULL) arrput(parent->children, h); From e20684f89ba3001fa79b15ba60bcba4cce00b359 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 23 Jul 2026 00:56:13 -0700 Subject: [PATCH 012/168] remove mime type stuff for now Windows's built in function for getting mime type sucks, and I don't want to have to vendor in libmagic. We'll leave this as something the user can handle themselves. --- include/Mw/LowLevel.h | 1 - include/Mw/StringDefs.h | 1 - src/backend/gdi.c | 43 +++-------------------------------------- src/core.c | 6 ------ src/lowlevel.c | 1 - 5 files changed, 3 insertions(+), 49 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 6089e48..0c53bd3 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -39,7 +39,6 @@ struct _MwLLCommon { int type; int coordinate_type; MwBool supports_transparency; - const char** known_mime_types; MwLLHandler handler; }; diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 5f9e3e4..885e07e 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -63,7 +63,6 @@ #define MwNforeground "Sforeground" #define MwNsubForeground "SsubForeground" #define MwNtitleForeground "StitleForeground" -#define MwNacceptedMimeType "SacceptedMimeType" #define MwNvulkanExtension "SEvulkanExtension" diff --git a/src/backend/gdi.c b/src/backend/gdi.c index e9f3d4c..aa5f7c1 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -20,15 +20,6 @@ static struct symtbl { UINT(WINAPI* DragQueryFileW)(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch); UINT(WINAPI* DragQueryFileA)(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch); - HRESULT(WINAPI* FindMimeFromData)( - LPBC pBC, - LPCWSTR pwzUrl, - LPVOID pBuffer, - DWORD cbSize, - LPCWSTR pwzMimeProposed, - DWORD dwMimeFlags, - LPWSTR* ppwzMimeOut, - DWORD dwReserved); void (*DragAcceptFiles)(HWND hWnd, BOOL fAccept); void (*DragFinish)(HDROP hDrop); } wsymtbl; @@ -188,36 +179,9 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); for(i = 0; i < count; i++) { - wchar_t path[MAX_PATH]; - char path_normal[MAX_PATH]; - char* mime_type_normal; - wchar_t* mime_type = NULL; - int mime_type_size; - HRESULT hr; - int i; - - wsymtbl.DragQueryFileW(hDrop, i, path, MAX_PATH); - wsymtbl.DragQueryFileA(hDrop, i, path_normal, MAX_PATH); - hr = wsymtbl.FindMimeFromData(NULL, path, NULL, 0, - NULL, 0, &mime_type, 0x0); - - mime_type_size = WideCharToMultiByte(CP_ACP, 0, mime_type, -1, NULL, 0, NULL, FALSE); - mime_type_normal = malloc(sizeof(mime_type_size)); - WideCharToMultiByte(CP_ACP, 0, mime_type, -1, mime_type_normal, mime_type_size, NULL, FALSE); - - if(mime_type_size == 0) { - printf("Error converting mime type to multi-byte: %ld\n", GetLastError()); - } else { - if(u->ll->common.known_mime_types) { - for(n = 0; n < arrlen(u->ll->common.known_mime_types); n++) { - if(strcmp(mime_type_normal, u->ll->common.known_mime_types[n]) == 0) { - MwLLDispatch(u->ll, drag_and_drop, path_normal); - } - } - } else { - MwLLDispatch(u->ll, drag_and_drop, path_normal); - } - } + char path[MAX_PATH]; + wsymtbl.DragQueryFileA(hDrop, i, path, MAX_PATH); + MwLLDispatch(u->ll, drag_and_drop, path); } wsymtbl.DragFinish(hDrop); break; @@ -1106,7 +1070,6 @@ static int MwLLGDICallInitImpl(void) { SHELL32_FUNC(DragQueryFileA); SHELL32_FUNC(DragAcceptFiles); SHELL32_FUNC(DragFinish); - URLMON_FUNC(FindMimeFromData); wsymtbl.has_drag_and_drop = MwTRUE; } diff --git a/src/core.c b/src/core.c index d1a5d9b..eb81536 100644 --- a/src/core.c +++ b/src/core.c @@ -707,12 +707,6 @@ void MwSetText(MwWidget handle, const char* key, const char* value) { if(strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0) { MwForceRender(handle); } - - if(strcmp(key, MwNacceptedMimeType) == 0) { - if(handle->lowlevel != NULL) { - arrput(handle->lowlevel->common.known_mime_types, value); - } - } } void MwSetVoid(MwWidget handle, const char* key, void* value) { diff --git a/src/lowlevel.c b/src/lowlevel.c index aca10c2..38a1ab0 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -64,7 +64,6 @@ void MwLLCreateCommon(MwLL handle) { memset(handle->common.handler, 0, sizeof(*handle->common.handler)); handle->common.supports_transparency = 0; - handle->common.known_mime_types = NULL; } void MwLLDestroyCommon(MwLL handle) { From f6c129b31c479e5f2ae31c025b99e9d204e8f386 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 23 Jul 2026 01:00:52 -0700 Subject: [PATCH 013/168] win32: pass utf8 function to dnd --- src/backend/gdi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index aa5f7c1..d4a8418 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -19,7 +19,6 @@ static struct symtbl { HRESULT(WINAPI* DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); UINT(WINAPI* DragQueryFileW)(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch); - UINT(WINAPI* DragQueryFileA)(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch); void (*DragAcceptFiles)(HWND hWnd, BOOL fAccept); void (*DragFinish)(HDROP hDrop); } wsymtbl; @@ -179,8 +178,13 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); for(i = 0; i < count; i++) { + wchar_t wpath[MAX_PATH]; char path[MAX_PATH]; - wsymtbl.DragQueryFileA(hDrop, i, path, MAX_PATH); + wsymtbl.DragQueryFileW(hDrop, i, wpath, MAX_PATH); + + memset(path, 0, sizeof(path)); + WideCharToMultiByte(CP_UTF8, 0, wpath, -1, path, sizeof(path) - 1, NULL, NULL); + MwLLDispatch(u->ll, drag_and_drop, path); } wsymtbl.DragFinish(hDrop); @@ -1067,7 +1071,6 @@ static int MwLLGDICallInitImpl(void) { } SHELL32_FUNC(DragQueryFileW); - SHELL32_FUNC(DragQueryFileA); SHELL32_FUNC(DragAcceptFiles); SHELL32_FUNC(DragFinish); From 39a458d80f34949a2c6a5242785b45884381ca2e Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 23 Jul 2026 18:24:56 +0900 Subject: [PATCH 014/168] win32: remove unused urlmon dep --- src/backend/gdi.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index d4a8418..7f4ae6d 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -13,7 +13,6 @@ typedef struct userdata { static struct symtbl { void* lib_dwmapi; void* shell32lib; - void* urlmonlib; MwBool has_drag_and_drop; HRESULT(WINAPI* DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); @@ -1055,20 +1054,12 @@ static int MwLLGDICallInitImpl(void) { if(!(wsymtbl.shell32lib = LoadLibrary("shell32.dll"))) { goto dnd_error; }; - if(!(wsymtbl.urlmonlib = LoadLibrary("Urlmon.dll"))) { - goto dnd_error; - }; #define SHELL32_FUNC(x) \ if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.shell32lib, #x))) { \ printf(#x "not found, drag and drop will not be supported"); \ goto dnd_error; \ } -#define URLMON_FUNC(x) \ - if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.urlmonlib, #x))) { \ - printf(#x "not found, drag and drop will not be supported"); \ - goto dnd_error; \ - } SHELL32_FUNC(DragQueryFileW); SHELL32_FUNC(DragAcceptFiles); From 7c2ab989fa30ef5a7641c927c93f2a49c31f4fb9 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 24 Jul 2026 20:51:17 -0700 Subject: [PATCH 015/168] formatting --- include/Mw/TypeDefs.h | 2 +- src/backend/gdi.c | 35 ++++++++++++++++++----------------- src/core.c | 40 ++++++++++++++++++++-------------------- 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index fbc91fa..ad072a3 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -274,7 +274,7 @@ struct _MwClass { MwHandlerChildrenProp children_prop_change; MwHandlerClipboardReceived clipboard; MwHandlerProps props_change; - MwHandler drag_and_drop; + MwHandler drag_and_drop; void* reserved2; void* reserved3; }; diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 7f4ae6d..2abc8b3 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -77,7 +77,7 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch(msg) { case WM_INITDIALOG: - return TRUE; + return TRUE; case WM_PAINT: { PAINTSTRUCT ps; @@ -168,25 +168,26 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { MwLLDispatch(u->ll, up, &p); break; } - case WM_DROPFILES: { - HDROP hDrop = (HDROP)wp; - UINT count; - UINT i, n; - HRESULT hr; + case WM_DROPFILES: + { + HDROP hDrop = (HDROP)wp; + UINT count; + UINT i, n; + HRESULT hr; - count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); + count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); - for(i = 0; i < count; i++) { - wchar_t wpath[MAX_PATH]; - char path[MAX_PATH]; - wsymtbl.DragQueryFileW(hDrop, i, wpath, MAX_PATH); + for(i = 0; i < count; i++) { + wchar_t wpath[MAX_PATH]; + char path[MAX_PATH]; + wsymtbl.DragQueryFileW(hDrop, i, wpath, MAX_PATH); - memset(path, 0, sizeof(path)); - WideCharToMultiByte(CP_UTF8, 0, wpath, -1, path, sizeof(path) - 1, NULL, NULL); + memset(path, 0, sizeof(path)); + WideCharToMultiByte(CP_UTF8, 0, wpath, -1, path, sizeof(path) - 1, NULL, NULL); MwLLDispatch(u->ll, drag_and_drop, path); - } - wsymtbl.DragFinish(hDrop); + } + wsymtbl.DragFinish(hDrop); break; } case WM_MOUSEMOVE: @@ -612,9 +613,9 @@ static void MwLLNextEventImpl(MwLL handle) { handle->gdi.get_darktheme = 0; } while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { - if(GetMessage(&msg, NULL, 0, 0)) { + if(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); - DispatchMessage(&msg); + DispatchMessage(&msg); } } } diff --git a/src/core.c b/src/core.c index eb81536..251d255 100644 --- a/src/core.c +++ b/src/core.c @@ -145,8 +145,9 @@ static void llclosehandler(MwLL handle, void* data) { } static void llmovehandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; - MwPoint* p = data; + MwWidget h = (MwWidget)handle->common.user; + MwPoint* p = data; + h->mouse_point.x = p->x; h->mouse_point.y = p->y; @@ -193,15 +194,13 @@ static void llclipboardhandler(MwLL handle, void* data) { } static void lldraganddrophandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; - const char * p = data; + MwWidget h = (MwWidget)handle->common.user; + const char* p = data; if(MwGetInteger(h, MwNdisabled) == 1) return; - printf("%s\n",p); MwDispatchUserHandler(h, MwNdragAndDropHandler, data); } - /* if both of them are true * 1. widget class is not NULL * 2. parent is NULL @@ -282,20 +281,20 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, if(parent == NULL) h->top_step = 1; if(h->lowlevel != NULL) { - h->lowlevel->common.user = h; - h->lowlevel->common.handler->draw = lldrawhandler; - h->lowlevel->common.handler->up = lluphandler; - h->lowlevel->common.handler->down = lldownhandler; - h->lowlevel->common.handler->resize = llresizehandler; - h->lowlevel->common.handler->close = llclosehandler; - h->lowlevel->common.handler->move = llmovehandler; - h->lowlevel->common.handler->key = llkeyhandler; - h->lowlevel->common.handler->key_released = llkeyrelhandler; - h->lowlevel->common.handler->focus_in = llfocusinhandler; - h->lowlevel->common.handler->focus_out = llfocusouthandler; - h->lowlevel->common.handler->clipboard = llclipboardhandler; - h->lowlevel->common.handler->dark_theme = lldarkthemehandler; - h->lowlevel->common.handler->drag_and_drop = lldraganddrophandler; + h->lowlevel->common.user = h; + h->lowlevel->common.handler->draw = lldrawhandler; + h->lowlevel->common.handler->up = lluphandler; + h->lowlevel->common.handler->down = lldownhandler; + h->lowlevel->common.handler->resize = llresizehandler; + h->lowlevel->common.handler->close = llclosehandler; + h->lowlevel->common.handler->move = llmovehandler; + h->lowlevel->common.handler->key = llkeyhandler; + h->lowlevel->common.handler->key_released = llkeyrelhandler; + h->lowlevel->common.handler->focus_in = llfocusinhandler; + h->lowlevel->common.handler->focus_out = llfocusouthandler; + h->lowlevel->common.handler->clipboard = llclipboardhandler; + h->lowlevel->common.handler->dark_theme = lldarkthemehandler; + h->lowlevel->common.handler->drag_and_drop = lldraganddrophandler; } if(parent != NULL) arrput(parent->children, h); @@ -573,6 +572,7 @@ int MwStep(MwWidget handle) { MwFreeWidget(handle); return 1; } + return 0; } From 974947b400577d56246197583b5b6b3d35d38863 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 26 Jul 2026 01:21:50 +0900 Subject: [PATCH 016/168] remove warnings --- src/backend/gdi.c | 4 +--- src/core.c | 3 ++- src/text/gdi.c | 2 +- src/widget/entry.c | 2 ++ 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 2abc8b3..71bfcfb 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -172,8 +172,7 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { { HDROP hDrop = (HDROP)wp; UINT count; - UINT i, n; - HRESULT hr; + UINT i; count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); @@ -1034,7 +1033,6 @@ static void MwLLSetupDragAndDropImpl(MwLL handle) { static int MwLLGDICallInitImpl(void) { void* ntdll; - HRESULT hr; memset(&wsymtbl, 0, sizeof(wsymtbl)); diff --git a/src/core.c b/src/core.c index 251d255..4d584d0 100644 --- a/src/core.c +++ b/src/core.c @@ -195,7 +195,6 @@ static void llclipboardhandler(MwLL handle, void* data) { static void lldraganddrophandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - const char* p = data; if(MwGetInteger(h, MwNdisabled) == 1) return; MwDispatchUserHandler(h, MwNdragAndDropHandler, data); @@ -328,7 +327,9 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, #if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT) if(IsFirstVisible(h)) { +#ifdef USE_STB_TRUETYPE font_setup: +#endif h->root_font = MwFontLoad(MwTTFData, MwTTFDataSize); h->root_boldfont = MwFontLoad(MwBoldTTFData, MwBoldTTFDataSize); h->root_monofont = MwFontLoad(MwMonospaceTTFData, MwMonospaceTTFDataSize); diff --git a/src/text/gdi.c b/src/text/gdi.c index b5f3ced..b965e2d 100644 --- a/src/text/gdi.c +++ b/src/text/gdi.c @@ -245,7 +245,7 @@ static BOOL WINAPI _RemoveFontMemResourceExPolyFill(HANDLE h) { int MwFL_GDISetup(void) { void* gdilib = LoadLibrary("gdi32.dll"); if(!gdilib) { - printf("gdi32.dll not found(?????)\n"); + printf("gdi32.dll not found(what)\n"); } else { _AddFontMemResourceEx = (void*)GetProcAddress(gdilib, "AddFontMemResourceEx"); if(!_AddFontMemResourceEx) { diff --git a/src/widget/entry.c b/src/widget/entry.c index dd867d7..44f5a42 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -180,6 +180,8 @@ static void mouse_down(MwWidget handle, void* ptr) { MwEntry t = handle->internal; MwWidget topmost_parent = handle->parent; + (void)ptr; + while(topmost_parent->parent) topmost_parent = topmost_parent->parent; for(i = 0; i < arrlen(topmost_parent->monitored_entries); i++) { From 85b66d0d9af1e0654d81175d39f6bab54910497f Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 26 Jul 2026 01:44:01 +0900 Subject: [PATCH 017/168] fix font rendering --- include/Mw/LowLevel/GDI.h | 3 +-- include/Mw/StringDefs.h | 1 - src/backend/cairo.c | 12 ++++++------ src/backend/gdi.c | 16 +++++++++------- src/core.c | 2 +- src/dialog/messagebox.c | 6 +++--- src/text/gdi.c | 6 +++--- src/text/text.c | 1 + src/widget/entry.c | 2 +- 9 files changed, 25 insertions(+), 24 deletions(-) diff --git a/include/Mw/LowLevel/GDI.h b/include/Mw/LowLevel/GDI.h index e505b0a..d2e2473 100644 --- a/include/Mw/LowLevel/GDI.h +++ b/include/Mw/LowLevel/GDI.h @@ -34,8 +34,7 @@ struct _MwLLGDI { struct _MwLLGDIColor { struct _MwLLCommonColor common; - COLORREF color; - HBRUSH brush; + HBRUSH brush; }; struct _MwLLGDIPixmap { diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 885e07e..6ad4e46 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -64,7 +64,6 @@ #define MwNsubForeground "SsubForeground" #define MwNtitleForeground "StitleForeground" - #define MwNvulkanExtension "SEvulkanExtension" #define MwNvulkanLayer "SEvulkanLayer" #define MwNvulkanConfig "VEvulkanConfig" diff --git a/src/backend/cairo.c b/src/backend/cairo.c index d70de1b..65380fb 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -212,8 +212,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -257,10 +257,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 71bfcfb..89caab2 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -170,9 +170,9 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { } case WM_DROPFILES: { - HDROP hDrop = (HDROP)wp; - UINT count; - UINT i; + HDROP hDrop = (HDROP)wp; + UINT count; + UINT i; count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); @@ -524,7 +524,8 @@ static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { } static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { - HDC dc = GetDC(handle->gdi.hWnd); + HDC dc = GetDC(handle->gdi.hWnd); + COLORREF color; if(r > 255) r = 255; if(g > 255) g = 255; @@ -533,9 +534,10 @@ static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { if(g < 0) g = 0; if(b < 0) b = 0; + color = GetNearestColor(dc, RGB(r, g, b)); + if(c->gdi.brush != NULL) DeleteObject(c->gdi.brush); - c->gdi.color = GetNearestColor(dc, RGB(r, g, b)); - c->gdi.brush = CreateSolidBrush(c->gdi.color); + c->gdi.brush = CreateSolidBrush(color); c->common.red = r; c->common.green = g; c->common.blue = b; @@ -1032,7 +1034,7 @@ static void MwLLSetupDragAndDropImpl(MwLL handle) { } static int MwLLGDICallInitImpl(void) { - void* ntdll; + void* ntdll; memset(&wsymtbl, 0, sizeof(wsymtbl)); diff --git a/src/core.c b/src/core.c index 4d584d0..9d149d8 100644 --- a/src/core.c +++ b/src/core.c @@ -194,7 +194,7 @@ static void llclipboardhandler(MwLL handle, void* data) { } static void lldraganddrophandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.user; if(MwGetInteger(h, MwNdisabled) == 1) return; MwDispatchUserHandler(h, MwNdragAndDropHandler, data); diff --git a/src/dialog/messagebox.c b/src/dialog/messagebox.c index 6a96f6d..ff72bc8 100644 --- a/src/dialog/messagebox.c +++ b/src/dialog/messagebox.c @@ -68,9 +68,9 @@ MwWidget MwMessageBox(MwWidget handle, const char* text, const char* title, unsi if(flag & MwMB_BUTTONYES) spawn_button(window, w - (x += 8 + 80), h - 8 - 24, MwMB_BUTTONYES, "Yes"); if((flag & MwMB_ICONMASK) != 0) { - MwWidget icon; - MwLLPixmap px; - MwU32* data = NULL; + MwWidget icon; + MwLLPixmap px; + MwU32* data = NULL; icon = MwCreateWidget(MwImageClass, "image", window, 8, (h - 48) / 2, 48, 48); diff --git a/src/text/gdi.c b/src/text/gdi.c index b965e2d..97e6870 100644 --- a/src/text/gdi.c +++ b/src/text/gdi.c @@ -28,10 +28,10 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c tw = MwTextWidth(handle, ttf, text); th = MwTextHeight(handle, ttf, text); - if(handle->lowlevel->common.type == MwLLBackendGDI && MwGetInteger(handle, MwNmodernLook) == MwFALSE) { + if(handle->lowlevel->common.type == MwLLBackendGDI) { HFONT old_font = SelectObject(handle->lowlevel->gdi.hDC, ttf->font); int old_bkmode = SetBkMode(handle->lowlevel->gdi.hDC, TRANSPARENT); - COLORREF old_color = SetTextColor(handle->lowlevel->gdi.hDC, color->gdi.color); + COLORREF old_color = SetTextColor(handle->lowlevel->gdi.hDC, RGB(color->common.red, color->common.green, color->common.blue)); TextOut(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t, strlen(t)); @@ -180,7 +180,7 @@ static HANDLE WINAPI _AddFontMemResourceExPolyFill(PVOID pFileView, DWORD cjSize CHAR temp_path_dir[MAX_PATH]; CHAR temp_path_name[MAX_PATH]; HANDLE tempFile = NULL; - DWORD hr; + DWORD hr; (void)pvResrved; diff --git a/src/text/text.c b/src/text/text.c index 9ad1e94..9d7d184 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -91,6 +91,7 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, fadedColor->common.red = fadedColor->common.red + (c->common.red - fadedColor->common.red) * 0.5; fadedColor->common.green = fadedColor->common.green + (c->common.green - fadedColor->common.green) * 0.5; fadedColor->common.blue = fadedColor->common.blue + (c->common.blue - fadedColor->common.blue) * 0.5; + MwLLColorUpdate(handle->lowlevel, fadedColor, fadedColor->common.red, fadedColor->common.green, fadedColor->common.blue); MwLLFreeColor(c); } diff --git a/src/widget/entry.c b/src/widget/entry.c index 44f5a42..9d423bf 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -9,7 +9,7 @@ static int wcreate(MwWidget handle) { t->right = 0; t->length = 0; t->cursor_blink_timer = 0; - t->active = 0; + t->active = 0; handle->internal = t; while(topmost_parent->parent) topmost_parent = topmost_parent->parent; From bde66f13a517c18bc80c1ff30b809c508ccb2864 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 8 Aug 2026 15:26:42 -0700 Subject: [PATCH 018/168] fix the wall of warnings on VS2022 --- src/draw.c | 158 +++++++++++++++++++++++++++++------------------------ 1 file changed, 87 insertions(+), 71 deletions(-) diff --git a/src/draw.c b/src/draw.c index ce86d90..2314c02 100644 --- a/src/draw.c +++ b/src/draw.c @@ -43,9 +43,9 @@ static void color_set_disabled_if_disabled(MwWidget handle, MwLLColor rgb) { MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { - rgb->common.red = rgb->common.red + (c->common.red - rgb->common.red) * 0.5; - rgb->common.green = rgb->common.green + (c->common.green - rgb->common.green) * 0.5; - rgb->common.blue = rgb->common.blue + (c->common.blue - rgb->common.blue) * 0.5; + rgb->common.red = (MwU8)(rgb->common.red + (c->common.red - rgb->common.red) * 0.5); + rgb->common.green = (MwU8)(rgb->common.green + (c->common.green - rgb->common.green) * 0.5); + rgb->common.blue = (MwU8)(rgb->common.blue + (c->common.blue - rgb->common.blue) * 0.5); MwLLColorUpdate(handle->lowlevel, rgb, rgb->common.red, rgb->common.green, rgb->common.blue); MwLLFreeColor(c); @@ -124,8 +124,11 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { int ColorDiff = get_color_diff(handle); double darkenStep = (ColorDiff / 2.) / rect->height; unsigned long sz = 1 * rect->height * 4; - unsigned char* data = malloc(sz); + unsigned char* data = malloc(sz*2); MwRect r = *rect; + if(!data) { + return; + } if(rect->width <= 0 || rect->height <= 0) { free(data); return; @@ -138,7 +141,7 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { r.height -= 2; for(y = 0; y < rect->height; y++) { - MwLLColor col = MwLightenColor(handle, color, -darken, -darken, -darken); + MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); int idx = y * 4; color_set_disabled_if_disabled(handle, col); data[idx] = col->common.red; @@ -458,11 +461,11 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p1[1].x = rect->x; p1[1].y = rect->y + rect->height; - p1[2].x = rect->x + c * border; - p1[2].y = rect->y + rect->height - s * border; + p1[2].x = (int)(rect->x + c * border); + p1[2].y = (int)(rect->y + rect->height - s * border); p1[3].x = rect->x + rect->width / 2; - p1[3].y = rect->y + border; + p1[3].y = (int)(rect->y + border); p2[0].x = rect->x + rect->width / 2; p2[0].y = rect->y; @@ -470,14 +473,14 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p2[1].x = rect->x + rect->width; p2[1].y = rect->y + rect->height; - p2[2].x = rect->x + rect->width - c * border; - p2[2].y = rect->y + rect->height - s * border; + p2[2].x = (int)(rect->x + rect->width - c * border); + p2[2].y = (int)(rect->y + rect->height - s * border); p2[3].x = rect->x + rect->width / 2; - p2[3].y = rect->y + border; + p2[3].y = (int)(rect->y + border); - p3[0].x = rect->x + c * border; - p3[0].y = rect->y + rect->height - s * border; + p3[0].x = (int)(rect->x + c * border); + p3[0].y = (int)(rect->y + rect->height - s * border); p3[1].x = rect->x; p3[1].y = rect->y + rect->height; @@ -485,30 +488,30 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p3[2].x = rect->x + rect->width; p3[2].y = rect->y + rect->height; - p3[3].x = rect->x + rect->width - c * border; - p3[3].y = rect->y + rect->height - s * border; + p3[3].x = (int)(rect->x + rect->width - c * border); + p3[3].y = (int)(rect->y + rect->height - s * border); MwLLPolygon(handle->lowlevel, p1, 4, invert ? darker : lighter); MwLLPolygon(handle->lowlevel, p2, 4, invert ? lighter : darker); MwLLPolygon(handle->lowlevel, p3, 4, invert ? lighter : darker); - p4[0].x = rect->x + c * border; - p4[0].y = rect->y + rect->height - s * border; + p4[0].x = (int)(rect->x + c * border); + p4[0].y = (int)(rect->y + rect->height - s * border); - p4[1].x = rect->x + rect->width - c * border; - p4[1].y = rect->y + rect->height - s * border; + p4[1].x = (int)(rect->x + rect->width - c * border); + p4[1].y = (int)(rect->y + rect->height - s * border); p4[2].x = rect->x + rect->width / 2; - p4[2].y = rect->y + border; + p4[2].y = (int)(rect->y + border); } else if(direction == MwSOUTH) { p1[0].x = rect->x; p1[0].y = rect->y; - p1[1].x = rect->x + c * border; - p1[1].y = rect->y + s * border; + p1[1].x = (int)(rect->x + c * border); + p1[1].y = (int)(rect->y + s * border); - p1[2].x = rect->x + rect->width - c * border; - p1[2].y = rect->y + s * border; + p1[2].x = (int)(rect->x + rect->width - c * border); + p1[2].y = (int)(rect->y + s * border); p1[3].x = rect->x + rect->width; p1[3].y = rect->y; @@ -516,11 +519,11 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p2[0].x = rect->x; p2[0].y = rect->y; - p2[1].x = rect->x + c * border; - p2[1].y = rect->y + s * border; + p2[1].x = (int)(rect->x + c * border); + p2[1].y = (int)(rect->y + s * border); p2[2].x = rect->x + rect->width / 2; - p2[2].y = rect->y + rect->height - border; + p2[2].y = (int)(rect->y + rect->height - border); p2[3].x = rect->x + rect->width / 2; p2[3].y = rect->y + rect->height; @@ -532,32 +535,32 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p3[1].y = rect->y + rect->height; p3[2].x = rect->x + rect->width / 2; - p3[2].y = rect->y + rect->height - border; + p3[2].y = (int)(rect->y + rect->height - border); - p3[3].x = rect->x + rect->width - c * border; - p3[3].y = rect->y + s * border; + p3[3].x = (int)(rect->x + rect->width - c * border); + p3[3].y = (int)(rect->y + s * border); MwLLPolygon(handle->lowlevel, p1, 4, invert ? darker : lighter); MwLLPolygon(handle->lowlevel, p2, 4, invert ? darker : lighter); MwLLPolygon(handle->lowlevel, p3, 4, invert ? lighter : darker); - p4[0].x = rect->x + c * border; - p4[0].y = rect->y + s * border; + p4[0].x = (int)(rect->x + c * border); + p4[0].y = (int)(rect->y + s * border); - p4[1].x = rect->x + rect->width - c * border; - p4[1].y = rect->y + s * border; + p4[1].x = (int)(rect->x + rect->width - c * border); + p4[1].y = (int)(rect->y + s * border); p4[2].x = rect->x + rect->width / 2; - p4[2].y = rect->y + rect->height - border; + p4[2].y = (int)(rect->y + rect->height - border); } else if(direction == MwEAST) { p1[0].x = rect->x; p1[0].y = rect->y; - p1[1].x = rect->x + c * border; - p1[1].y = rect->y + s * border; + p1[1].x = (int)(rect->x + c * border); + p1[1].y = (int)(rect->y + s * border); - p1[2].x = rect->x + c * border; - p1[2].y = rect->y + rect->height - s * border; + p1[2].x = (int)(rect->x + c * border); + p1[2].y = (int)(rect->y + rect->height - s * border); p1[3].x = rect->x; p1[3].y = rect->y + rect->height; @@ -568,14 +571,14 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p2[1].x = rect->x + rect->width; p2[1].y = rect->y + rect->height / 2; - p2[2].x = rect->x + rect->width - border; + p2[2].x = (int)(rect->x + rect->width - border); p2[2].y = rect->y + rect->height / 2; - p2[3].x = rect->x + c * border; - p2[3].y = rect->y + s * border; + p2[3].x = (int)(rect->x + c * border); + p2[3].y = (int)(rect->y + s * border); - p3[0].x = rect->x + c * border; - p3[0].y = rect->y + rect->height - s * border; + p3[0].x = (int)(rect->x + c * border); + p3[0].y = (int)(rect->y + rect->height - s * border); p3[1].x = rect->x; p3[1].y = rect->y + rect->height; @@ -583,30 +586,30 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p3[2].x = rect->x + rect->width; p3[2].y = rect->y + rect->height / 2; - p3[3].x = rect->x + rect->width - border; + p3[3].x = (int)(rect->x + rect->width - border); p3[3].y = rect->y + rect->height / 2; MwLLPolygon(handle->lowlevel, p1, 4, invert ? darker : lighter); MwLLPolygon(handle->lowlevel, p2, 4, invert ? darker : lighter); MwLLPolygon(handle->lowlevel, p3, 4, invert ? lighter : darker); - p4[0].x = rect->x + rect->width - border; + p4[0].x = (int)(rect->x + rect->width - border); p4[0].y = rect->y + rect->height / 2; - p4[1].x = rect->x + c * border; - p4[1].y = rect->y + rect->height - s * border; + p4[1].x = (int)(rect->x + c * border); + p4[1].y = (int)(rect->y + rect->height - s * border); - p4[2].x = rect->x + c * border; - p4[2].y = rect->y + s * border; + p4[2].x = (int)(rect->x + c * border); + p4[2].y = (int)(rect->y + s * border); } else if(direction == MwWEST) { p1[0].x = rect->x; p1[0].y = rect->y + rect->height / 2; - p1[1].x = rect->x + border; + p1[1].x = (int)(rect->x + border); p1[1].y = rect->y + rect->height / 2; - p1[2].x = rect->x + rect->width - c * border; - p1[2].y = rect->y + s * border; + p1[2].x = (int)(rect->x + rect->width - c * border); + p1[2].y = (int)(rect->y + s * border); p1[3].x = rect->x + rect->width; p1[3].y = rect->y; @@ -614,11 +617,11 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p2[0].x = rect->x; p2[0].y = rect->y + rect->height / 2; - p2[1].x = rect->x + border; + p2[1].x = (int)(rect->x + border); p2[1].y = rect->y + rect->height / 2; - p2[2].x = rect->x + rect->width - c * border; - p2[2].y = rect->y + rect->height - s * border; + p2[2].x = (int)(rect->x + rect->width - c * border); + p2[2].y = (int)(rect->y + rect->height - s * border); p2[3].x = rect->x + rect->width; p2[3].y = rect->y + rect->height; @@ -626,11 +629,11 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p3[0].x = rect->x + rect->width; p3[0].y = rect->y; - p3[1].x = rect->x + rect->width - c * border; - p3[1].y = rect->y + s * border; + p3[1].x = (int)(rect->x + rect->width - c * border); + p3[1].y = (int)(rect->y + s * border); - p3[2].x = rect->x + rect->width - c * border; - p3[2].y = rect->y + rect->height - s * border; + p3[2].x = (int)(rect->x + rect->width - c * border); + p3[2].y = (int)(rect->y + rect->height - s * border); p3[3].x = rect->x + rect->width; p3[3].y = rect->y + rect->height; @@ -639,14 +642,14 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, MwLLPolygon(handle->lowlevel, p2, 4, invert ? lighter : darker); MwLLPolygon(handle->lowlevel, p3, 4, invert ? lighter : darker); - p4[0].x = rect->x + border; + p4[0].x = (int)(rect->x + border); p4[0].y = rect->y + rect->height / 2; - p4[1].x = rect->x + rect->width - c * border; - p4[1].y = rect->y + rect->height - s * border; + p4[1].x = (int)(rect->x + rect->width - c * border); + p4[1].y = (int)(rect->y + rect->height - s * border); - p4[2].x = rect->x + rect->width - c * border; - p4[2].y = rect->y + s * border; + p4[2].x = (int)(rect->x + rect->width - c * border); + p4[2].y = (int)(rect->y + s * border); } MwLLPolygon(handle->lowlevel, p4, 3, col); @@ -830,13 +833,13 @@ void MwPixmapReloadRaw(MwLLPixmap px, unsigned char* rgb) { a /= 255; if(a != 0) { - pout[0] = pin[0] * a; - pout[1] = pin[1] * a; - pout[2] = pin[2] * a; + pout[0] = (unsigned char)(pin[0] * a); + pout[1] = (unsigned char)(pin[1] * a); + pout[2] = (unsigned char)(pin[2] * a); - pout[0] += base->common.red * (1 - a); - pout[1] += base->common.green * (1 - a); - pout[2] += base->common.blue * (1 - a); + pout[0] += (unsigned char)(base->common.red * (1 - a)); + pout[1] += (unsigned char)(base->common.green * (1 - a)); + pout[2] += (unsigned char)(base->common.blue * (1 - a)); pout[3] = 255; } } @@ -868,6 +871,11 @@ MwLLPixmap MwLoadIcon(MwWidget handle, MwU32* data) { MwLLPixmap px; int i; + if(!rgba) { + printf("Null malloc! out of memory?\n"); + return NULL; + } + memset(rgba, 0, width * height * 4); for(i = 0; i < width * height; i++) { @@ -905,7 +913,11 @@ MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { sh_new_strdup(c); +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + sscanf_s(data[0], "%d %d %d %d", &col, &row, &colors, &cpp); +#else sscanf(data[0], "%d %d %d %d", &col, &row, &colors, &cpp); +#endif for(i = 0; i < colors; i++) { char k[128]; @@ -942,6 +954,10 @@ MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { rgb = malloc(row * col * 4); comp = malloc(cpp + 1); + if(!rgb || !comp) { + printf("Null malloc! Out of memory?"); + return NULL; + } comp[cpp] = 0; for(y = 0; y < row; y++) { for(x = 0; x < col; x++) { From 6f976ae0cedc8d5684ec7152bd29adaf96c8e1e3 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 8 Aug 2026 16:02:53 -0700 Subject: [PATCH 019/168] more fuller suite of error mutes for vs2022 --- CMakeLists.txt | 2 ++ src/abstract/directory.c | 32 +++++++++++--------- src/backend/gdi.c | 63 ++++++++++++++++++++++++++++++++++++++-- src/dialog/colorpicker.c | 22 +++++++------- src/string.c | 51 ++++++++++++++++++++++++++++++-- src/text/text.c | 21 ++++++++++++-- src/widget/button.c | 12 ++++---- src/widget/listbox.c | 12 +++++++- src/widget/progressbar.c | 2 +- src/widget/scrollbar.c | 6 ++-- src/widget/viewport.c | 10 +++++-- 11 files changed, 189 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e7aefde..b9882e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,11 +330,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_SYSTEM_NAME STREQUAL "MSYS") USE_GDI ) list(APPEND LIBRARIES gdi32 ole32 winmm uuid) + if(NOT MSVC) target_link_options( Mw PRIVATE -static-libgcc ) + endif() elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") # target_sources( # Mw diff --git a/src/abstract/directory.c b/src/abstract/directory.c index ac5a382..65db1c8 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -19,15 +19,18 @@ typedef struct dir { void* MwDirectoryOpen(const char* path) { dir_t* dir = malloc(sizeof(*dir)); -#ifdef _WIN32 - char* p = malloc(strlen(path) + 2 + 1); - strcpy(p, path); - if(strchr(path, '/') != NULL) { - strcat(p, "/"); - } else { - strcat(p, "\\"); + if(!dir) { + printf("Out Of Memory\n"); + return NULL; } - strcat(p, "*"); +#ifdef _WIN32 + char* p = MwStringDuplicate(path); + if(strchr(path, '/') != NULL) { + MwStringConcat(p, "/"); + } else { + MwStringConcat(p, "\\"); + } + MwStringConcat(p, "*"); if((dir->hFind = FindFirstFile(p, &dir->ffd)) == INVALID_HANDLE_VALUE) { free(p); free(dir); @@ -65,6 +68,10 @@ void MwDirectoryClose(void* handle) { MwDirectoryEntry* MwDirectoryRead(void* handle) { dir_t* dir = handle; MwDirectoryEntry* entry = malloc(sizeof(*entry)); + if(!entry) { + printf("Out Of Memory\n"); + return NULL; + } #ifdef _WIN32 ULARGE_INTEGER* l; @@ -170,8 +177,8 @@ static void MwDirectoryJoinSingle(char* target, char* p) { b[0] = DIRSEP; b[1] = 0; - strcat(target, b); - strcat(target, p); + MwStringConcat(target, b); + MwStringConcat(target, p); } for(i = strlen(target) - 1; i >= 0; i--) { @@ -187,17 +194,16 @@ static void MwDirectoryJoinSingle(char* target, char* p) { b[0] = DIRSEP; b[1] = 0; - strcat(target, b); + MwStringConcat(target, b); } } char* MwDirectoryJoin(char* a, char* b) { - char* p = malloc(strlen(a) + 1 + strlen(b) + 1); + char* p = MwStringDuplicate(a); char* bdup = MwStringDuplicate(b); char* b2 = bdup; int i; - strcpy(p, a); for(i = strlen(p) - 1; i >= 0; i--) { if(p[i] == DIRSEP) { p[i] = 0; diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 89caab2..eace1d3 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -397,6 +397,11 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { userdata_t* u = malloc(sizeof(*u)); WNDCLASSEX wc; + if(!r || !u) { + printf("Out Of Memory\n"); + return NULL; + } + memset(&wc, 0, sizeof(wc)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; @@ -482,6 +487,11 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0)); int i; + if(!p) { + printf("Out Of Memory\n"); + return; + } + for(i = 0; i < points_count; i++) { p[i].x = points[i].x; p[i].y = points[i].y; @@ -516,6 +526,11 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { MwLLColor c = malloc(sizeof(*c)); + if(!c) { + printf("Out Of Memory\n"); + return NULL; + } + c->gdi.brush = NULL; MwLLColorUpdate(handle, c, r, g, b); @@ -593,10 +608,20 @@ static void MwLLNextEventImpl(MwLL handle) { if(handle->gdi.get_clipboard) { HGLOBAL hg; if(OpenClipboard(handle->gdi.hWnd) != 0 && (hg = GetClipboardData(CF_TEXT)) != NULL) { - char* txt = malloc(GlobalSize(hg)); + int sz = GlobalSize(hg); + char* txt = malloc(sz); char* clp = GlobalLock(hg); + if(!txt || !clp) { + printf("Out of Memory\n"); + return; + } + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + strcpy_s(txt, sz, clp); +#else strcpy(txt, clp); +#endif GlobalUnlock(hg); CloseClipboard(); @@ -626,7 +651,17 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int wid HDC dc = GetDC(handle->gdi.hWnd); BITMAPINFOHEADER bmih; + if(!r) { + printf("Out Of Memory\n"); + return NULL; + } + r->common.raw = malloc(width * height * 4); + if(!r->common.raw) { + printf("Out Of Memory\n"); + return NULL; + } + memcpy(r->common.raw, data, 4 * width * height); r->common.width = width; @@ -666,6 +701,12 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap r) { words = malloc(w * r->common.height); words2 = malloc(w * r->common.height); + + if(!words || !words2) { + printf("Out Of Memory\n"); + return; + } + memset(words, 0, w * r->common.height); memset(words2, 0, w * r->common.height); for(y = 0; y < r->common.height; y++) { @@ -917,12 +958,30 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_ty (void)clipboard_type; if(OpenClipboard(handle->gdi.hWnd) != 0) { char* lock; + int sz = strlen(text) + 1; EmptyClipboard(); - hg = GlobalAlloc(GHND | GMEM_SHARE, strlen(text) + 1); + hg = GlobalAlloc(GHND | GMEM_SHARE, sz); + + if(!hg) { + printf("Out of Memory\n"); + return; + } lock = GlobalLock(hg); + + if(!lock) { + printf("Out Of Memory\n"); + GlobalUnlock(hg); + CloseClipboard(); + return; + } + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + strcpy_s(lock, sz, text); +#else strcpy(lock, text); +#endif GlobalUnlock(hg); SetClipboardData(CF_TEXT, hg); diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 926fddc..95fc283 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -110,9 +110,9 @@ static void color_picker_image_update(color_picker_t* picker) { picker->color_picker_image_data[i + 2] = 0; picker->color_picker_image_data[i + 3] = 0; } else if(dist >= 180.) { - picker->color_picker_image_data[i] = dist; - picker->color_picker_image_data[i + 1] = dist; - picker->color_picker_image_data[i + 2] = dist; + picker->color_picker_image_data[i] = (unsigned char)dist; + picker->color_picker_image_data[i + 1] = (unsigned char)dist; + picker->color_picker_image_data[i + 2] = (unsigned char)dist; picker->color_picker_image_data[i + 3] = 255; } else { MwHSV hsv_v; @@ -121,26 +121,26 @@ static void color_picker_image_update(color_picker_t* picker) { double xd = (M_PI / 180.) * ((double)_x); double yd = (M_PI / 180.) * ((double)_y); - float angle = atan2(yd, xd) - M_PI; - float hue = (angle * 180.) / M_PI; + double angle = atan2(yd, xd) - M_PI; + double hue = (angle * 180.) / M_PI; if(hue < 0.0) { hue += 360; } - hsv_v.h = (hue) * (HSV_HUE_STEPS / 360.); - hsv_v.s = (dist) * (HSV_SAT_MAX / 180.); + hsv_v.h = (MwU8)((hue) * (HSV_HUE_STEPS / 360.)); + hsv_v.s = (MwU8)((dist) * (HSV_SAT_MAX / 180.)); picker->hue_table[n] = hsv_v; picker->hue_table[n].generated = 1; } hsv_v = picker->hue_table[n]; - hsv_v.v = HSV_VAL_MAX - (picker->value * HSV_VAL_MAX); + hsv_v.v = (MwU8)(HSV_VAL_MAX - (picker->value * HSV_VAL_MAX)); hsv2rgb(hsv_v.h, hsv_v.s, hsv_v.v, &color.red, &color.green, &color.blue); - picker->color_picker_image_data[i] = color.red; - picker->color_picker_image_data[i + 1] = color.green; - picker->color_picker_image_data[i + 2] = color.blue; + picker->color_picker_image_data[i] = (unsigned char)color.red; + picker->color_picker_image_data[i + 1] = (unsigned char)color.green; + picker->color_picker_image_data[i + 2] = (unsigned char)color.blue; picker->color_picker_image_data[i + 3] = 255; n++; diff --git a/src/string.c b/src/string.c index f56b9ac..c894b9a 100644 --- a/src/string.c +++ b/src/string.c @@ -1,21 +1,53 @@ #include char* MwStringDuplicate(const char* str) { - char* r = malloc(strlen(str) + 1); + int sz = strlen(str) + 1; + char* r = malloc(sz); + if(!r) { + printf("Out Of Memory\n"); + return NULL; + } + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + strcpy_s(r, sz, str); +#else strcpy(r, str); +#endif return r; } char* MwStringConcat(const char* str1, const char* str2) { - char* r = malloc(strlen(str1) + strlen(str2) + 1); + int sz = strlen(str1) + strlen(str2) + 1; + char* r = malloc(sz); + if(!r) { + printf("Out Of Memory\n"); + return NULL; + } + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + strcpy_s(r, sz, str1); + strcat_s(r, sz, str2); +#else strcpy(r, str1); strcat(r, str2); +#endif return r; } void MwStringSize(char* out, MwOffset size) { +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + if(size / 1024 == 0) { + sprintf_s(out, 255, "%d", (int)size); + } else if(size / 1024 / 1024 == 0) { + sprintf_s(out, 255, "%.1fK", (double)size / 1024); + } else if(size / 1024 / 1024 / 1024 == 0) { + sprintf_s(out, 255, "%.1fM", (double)size / 1024 / 1024); + } else { + sprintf_s(out, 255, "%.1fG", (double)size / 1024 / 1024 / 1024); + } +#else if(size / 1024 == 0) { sprintf(out, "%d", (int)size); } else if(size / 1024 / 1024 == 0) { @@ -25,16 +57,28 @@ void MwStringSize(char* out, MwOffset size) { } else { sprintf(out, "%.1fG", (double)size / 1024 / 1024 / 1024); } +#endif } void MwStringTime(char* out, time_t t) { struct tm* tm = localtime(&t); const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if(tm == NULL) { +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + sprintf_s(out, 255, "localtime error"); +#else sprintf(out, "localtime error"); +#endif + } else { +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + sprintf_s(out, 255, "%s %2d %02d:%02d %d", months[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, 1900 + tm->tm_year); +#else sprintf(out, "%s %2d %02d:%02d %d", months[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, 1900 + tm->tm_year); +#endif } } void MwStringPrintIntoBuffer(char* out, MwU32 size, const char* fmt, ...) { @@ -43,6 +87,9 @@ void MwStringPrintIntoBuffer(char* out, MwU32 size, const char* fmt, ...) { #if __STDC_VERSION__ >= 199901L vsnprintf(out, size, fmt, va); +/* MSVC2022 reports the STDC_VERSION as fucking 1994. Thanks Bill Gates. */ +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + vsprintf_s(out, size, fmt, va); #else vsprintf(out, fmt, va); #endif diff --git a/src/text/text.c b/src/text/text.c index 9d7d184..2bb89b6 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -88,9 +88,9 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, if(c != NULL) { fadedColor = MwLLAllocColor(handle->lowlevel, color->common.red, color->common.blue, color->common.green); - fadedColor->common.red = fadedColor->common.red + (c->common.red - fadedColor->common.red) * 0.5; - fadedColor->common.green = fadedColor->common.green + (c->common.green - fadedColor->common.green) * 0.5; - fadedColor->common.blue = fadedColor->common.blue + (c->common.blue - fadedColor->common.blue) * 0.5; + fadedColor->common.red = (MwU8)(fadedColor->common.red + (c->common.red - fadedColor->common.red) * 0.5); + fadedColor->common.green = (MwU8)(fadedColor->common.green + (c->common.green - fadedColor->common.green) * 0.5); + fadedColor->common.blue = (MwU8)(fadedColor->common.blue + (c->common.blue - fadedColor->common.blue) * 0.5); MwLLColorUpdate(handle->lowlevel, fadedColor, fadedColor->common.red, fadedColor->common.green, fadedColor->common.blue); MwLLFreeColor(c); @@ -110,6 +110,11 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, char* line = malloc(input - last + 1); int i; + if(!line) { + printf("Out Of Memory\n"); + return; + } + memcpy(line, last, input - last); line[input - last] = 0; @@ -177,6 +182,11 @@ int MwTextWidth(MwWidget handle, MwFLFont ttf, const char* text) { char* line = malloc(input - last + 1); int i; + if(!line) { + printf("Out Of Memory\n"); + return 1; + } + memcpy(line, last, input - last); line[input - last] = 0; @@ -250,6 +260,11 @@ static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, th = MwTextHeight(handle, NULL, text); px = malloc(tw * th * 4); + if(!px) { + printf("Out of Memory\n"); + return; + } + memset(px, 0, tw * th * 4); sx = 0; diff --git a/src/widget/button.c b/src/widget/button.c index 51337e6..7f1da57 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -55,11 +55,11 @@ static void draw(MwWidget handle) { double sh = (double)oh / px->common.height; if(sw < sh) { - r.width = px->common.width * sw; - r.height = px->common.height * sw; + r.width = (int)(px->common.width * sw); + r.height = (int)(px->common.height * sw); } else { - r.width = px->common.width * sh; - r.height = px->common.height * sh; + r.width = (int)(px->common.width * sh); + r.height = (int)(px->common.height * sh); } r.width -= MwGetInteger(handle, MwNpadding) * 2; r.height -= MwGetInteger(handle, MwNpadding) * 2; @@ -68,8 +68,8 @@ static void draw(MwWidget handle) { r.height = px->common.height; } - r.x += (double)(ow - r.width) / 2; - r.y += (double)(oh - r.height) / 2; + r.x += (int)((double)(ow - r.width) / 2); + r.y += (int)((double)(oh - r.height) / 2); MwLLDrawPixmap(handle->lowlevel, &r, px); } else { diff --git a/src/widget/listbox.c b/src/widget/listbox.c index 32be887..cc17362 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -203,11 +203,16 @@ static void frame_draw(MwWidget handle) { int seek = 0; int l = 0; char* old = str; + int sz = strlen(old) + 5; if(ind < 0) ind = 0; - str = malloc(strlen(old) + 5); + str = malloc(sz); +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + strcpy_s(str, sz, old); +#else strcpy(str, old); +#endif free(old); while(str[seek] != 0) { @@ -317,6 +322,11 @@ static void resize(MwWidget handle, int no_resize) { static int wcreate(MwWidget handle) { MwListBox lb = malloc(sizeof(*lb)); + if(!lb) { + printf("Out Of Memory\n"); + return 1; + } + memset(lb, 0, sizeof(*lb)); handle->internal = lb; diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index 3185c23..8adf028 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -34,7 +34,7 @@ static void draw(MwWidget handle) { r.width -= MwDefaultBorderWidth(handle) * 2; r.height -= MwDefaultBorderWidth(handle) * 2; - r.width = r.width * w; + r.width = (int)(r.width * w); MwDrawRect(handle, &r, fill); MwLLFreeColor(fill); diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index 346f818..3bd2fdf 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -28,7 +28,7 @@ static int calc_length(MwWidget handle) { int area = MwGetInteger(handle, MwNareaShown); if(area > len) area = len; - return max * (double)area / len; + return (int)(max * (double)area / len); } static int calc_position(MwWidget handle) { @@ -36,7 +36,7 @@ static int calc_position(MwWidget handle) { int len = MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue); int val = MwGetInteger(handle, MwNvalue); - return (max - calc_length(handle)) * (double)val / len; + return (int)((max - calc_length(handle)) * (double)val / len); } static void add_value(MwWidget handle, int mul) { @@ -54,7 +54,7 @@ static void add_value(MwWidget handle, int mul) { } static void draw(MwWidget handle) { - MwRect r, rt, rbar; + MwRect r = {0}, rt = {0}, rbar = {0}; MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwLLColor dark = MwLightenColor(handle, base, -64, -64, -64); MwScrollBar scr = handle->internal; diff --git a/src/widget/viewport.c b/src/widget/viewport.c index 2541b65..803c424 100644 --- a/src/widget/viewport.c +++ b/src/widget/viewport.c @@ -76,6 +76,12 @@ static void resize(MwWidget handle) { static int wcreate(MwWidget handle) { MwViewport vp = malloc(sizeof(*vp)); + + if(!vp) { + printf("Out Of Memory\n"); + return 1; + } + memset(vp, 0, sizeof(*vp)); handle->internal = vp; @@ -151,7 +157,7 @@ static void tick(MwWidget handle) { v = MwGetInteger(vp->vscroll, MwNvalue); mv = MwGetInteger(vp->vscroll, MwNmaxValue); l = MwGetInteger(vp->frame, MwNheight); - v = (mv - l) * (double)v / mv; + v = (int)((mv - l) * (double)v / mv); if(v < 0) v = 0; MwVaApply(vp->inframe, @@ -166,7 +172,7 @@ static void tick(MwWidget handle) { v = MwGetInteger(vp->hscroll, MwNvalue); mv = MwGetInteger(vp->hscroll, MwNmaxValue); l = MwGetInteger(vp->frame, MwNwidth); - v = (mv - l) * (double)v / mv; + v = (int)((mv - l) * (double)v / mv); if(v < 0) v = 0; MwVaApply(vp->inframe, From 9856979906a0236e2d4d4c071e9863d9ec0013dd Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 8 Aug 2026 16:24:23 -0700 Subject: [PATCH 020/168] Dynload winmm, which is weird but it fixes vs2022 builds --- CMakeLists.txt | 8 +++++++- include/Mw/LowLevel.h | 6 ++++++ include/Mw/MachDep.h | 1 + src/abstract/time.c | 2 +- src/core.c | 14 +++++++++++++- 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b9882e4..8866686 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ if(MW_TRY_VULKAN) if(${Vulkan_FOUND}) set(MW_BUILD_VULKAN ON) message(STATUS "Vulkan widget has been enabled") - else() + else( message(WARNING "Vulkan widget has been disabled") endif() endif() @@ -471,6 +471,12 @@ if(MW_BUILD_VULKAN) PRIVATE MW_VULKAN ) +else() + target_compile_definitions( + Mw + PRIVATE + MW_VULKAN_NO_INCLUDE + ) endif() target_compile_definitions( diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 0c53bd3..44c5b64 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -363,6 +363,12 @@ MWDECL int (*MwFLTextHeightWithText)(MwFLFont ttf, const char* text); MWDECL void* (*MwFLFontLoad)(unsigned char* data, unsigned int size, int px); MWDECL void (*MwFLFontFree)(void* handle); +#ifdef _WIN32 +void *MwLL_winmmLib; +long (__stdcall* MwLL_PFN_timeGetTime)(void); +unsigned int (__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); +#endif + #ifdef __cplusplus } #endif diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 4c98b24..c791157 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -26,6 +26,7 @@ #ifdef _MILSKO #include #include +#include #ifndef GWLP_USERDATA #define GWLP_USERDATA GWL_USERDATA #define GWLP_WNDPROC GWL_WNDPROC diff --git a/src/abstract/time.c b/src/abstract/time.c index 59e9774..892cd32 100644 --- a/src/abstract/time.c +++ b/src/abstract/time.c @@ -2,7 +2,7 @@ #if defined(_WIN32) long MwTimeGetTick(void) { - return timeGetTime(); + return MwLL_PFN_timeGetTime(); } void MwTimeSleep(int ms) { diff --git a/src/core.c b/src/core.c index 9d149d8..1087577 100644 --- a/src/core.c +++ b/src/core.c @@ -1090,7 +1090,19 @@ int MwLibraryInit(void) { int i; #ifdef _WIN32 - timeBeginPeriod(10); + /* + There's no Windows configuration that Milsko supports that doesn't have winmm. + However, uhh, Visual Studio 2022. For some fucking reason. + Thanks for coming to my TED Talk. + */ + char winmmPath[MAX_PATH] = {0}; + GetSystemDirectory(winmmPath, MAX_PATH); + strcat_s(winmmPath, MAX_PATH, "\\winmm.dll"); + MwLL_winmmLib = LoadLibraryA(winmmPath); + MwLL_PFN_timeGetTime = (void *)GetProcAddress(MwLL_winmmLib, "timeGetTime"); + MwLL_PFN_timeBeginPeriod = (void *)GetProcAddress(MwLL_winmmLib, "timeBeginPeriod"); + + MwLL_PFN_timeBeginPeriod(10); #endif #ifdef USE_WAYLAND From 054b085bcd055f66b7db081bcf2de12b076227f5 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 8 Aug 2026 16:32:11 -0700 Subject: [PATCH 021/168] fix compiles on machines where we have no vulkan --- CMakeLists.txt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8866686..1b565a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ if(MW_TRY_VULKAN) if(${Vulkan_FOUND}) set(MW_BUILD_VULKAN ON) message(STATUS "Vulkan widget has been enabled") - else( + else() message(WARNING "Vulkan widget has been disabled") endif() endif() @@ -466,17 +466,14 @@ if(MW_BUILD_VULKAN) ) endif() + check_include_files(vulkan/VULKAN.h HAS_VK_HEADER) + if(HAS_VK_HEADER) target_compile_definitions( Mw PRIVATE MW_VULKAN ) -else() - target_compile_definitions( - Mw - PRIVATE - MW_VULKAN_NO_INCLUDE - ) + endif() endif() target_compile_definitions( From ff823028cd59ac430d8ab54a20fe12edfd04d02a Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 9 Aug 2026 15:16:00 +0900 Subject: [PATCH 022/168] Update include/Mw/LowLevel.h --- include/Mw/LowLevel.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 44c5b64..6647672 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -364,9 +364,9 @@ MWDECL void* (*MwFLFontLoad)(unsigned char* data, unsigned int size, int px); MWDECL void (*MwFLFontFree)(void* handle); #ifdef _WIN32 -void *MwLL_winmmLib; -long (__stdcall* MwLL_PFN_timeGetTime)(void); -unsigned int (__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); +MWDECL void *MwLL_winmmLib; +MWDECL long (__stdcall* MwLL_PFN_timeGetTime)(void); +MWDECL unsigned int (__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); #endif #ifdef __cplusplus From 8e4774054ec0cdf10dbd4d24b76d4979658d4351 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 9 Aug 2026 15:16:32 +0900 Subject: [PATCH 023/168] Update src/lowlevel.c --- src/lowlevel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lowlevel.c b/src/lowlevel.c index 38a1ab0..2fe1535 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -1,5 +1,11 @@ #include +#ifdef _WIN32 +void *MwLL_winmmLib; +long (__stdcall* MwLL_PFN_timeGetTime)(void); +unsigned int (__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); +#endif + MwLL (*MwLLCreate)(MwLL parent, int x, int y, int width, int height) = NULL; void (*MwLLDestroy)(MwLL handle) = NULL; From 87f6dff101332da62d5147673a8bd688ab05308a Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 9 Aug 2026 15:19:31 +0900 Subject: [PATCH 024/168] Update include/Mw/MachDep.h --- include/Mw/MachDep.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index c791157..4c98b24 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -26,7 +26,6 @@ #ifdef _MILSKO #include #include -#include #ifndef GWLP_USERDATA #define GWLP_USERDATA GWL_USERDATA #define GWLP_WNDPROC GWL_WNDPROC From 6a205453a71f4d204d8b542683e8a8918250c8ec Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 9 Aug 2026 15:26:48 +0900 Subject: [PATCH 025/168] fix c89 discrepency --- src/abstract/directory.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/abstract/directory.c b/src/abstract/directory.c index 65db1c8..01c7331 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -68,13 +68,20 @@ void MwDirectoryClose(void* handle) { MwDirectoryEntry* MwDirectoryRead(void* handle) { dir_t* dir = handle; MwDirectoryEntry* entry = malloc(sizeof(*entry)); - if(!entry) { +#ifdef _WIN32 + ULARGE_INTEGER* l; +#elif defined(CLASSIC_MAC_OS) +#else + struct dirent* d; + struct stat s; + char* p; +#endif + + if(!entry) { printf("Out Of Memory\n"); return NULL; } #ifdef _WIN32 - ULARGE_INTEGER* l; - if(!dir->next) return NULL; entry->name = MwStringDuplicate(dir->ffd.cFileName); @@ -98,9 +105,6 @@ MwDirectoryEntry* MwDirectoryRead(void* handle) { #elif defined(CLASSIC_MAC_OS) /* todo */ #else - struct dirent* d; - struct stat s; - char* p; if((d = readdir(dir->dir)) == NULL) { free(entry); return NULL; From f652523963b933c86235a85c07146954179180f1 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 9 Aug 2026 15:27:54 +0900 Subject: [PATCH 026/168] fix another c89 issue --- src/abstract/directory.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/abstract/directory.c b/src/abstract/directory.c index 01c7331..ddf10e1 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -19,12 +19,13 @@ typedef struct dir { void* MwDirectoryOpen(const char* path) { dir_t* dir = malloc(sizeof(*dir)); - if(!dir) { + char * p; + if(!dir) { printf("Out Of Memory\n"); return NULL; } #ifdef _WIN32 - char* p = MwStringDuplicate(path); + p = MwStringDuplicate(path); if(strchr(path, '/') != NULL) { MwStringConcat(p, "/"); } else { From ca41b5936b48a346db4ba957c036a9e6687c68e0 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 9 Aug 2026 15:32:56 +0900 Subject: [PATCH 027/168] Update src/core.c --- src/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core.c b/src/core.c index 1087577..bc4645b 100644 --- a/src/core.c +++ b/src/core.c @@ -1095,9 +1095,10 @@ int MwLibraryInit(void) { However, uhh, Visual Studio 2022. For some fucking reason. Thanks for coming to my TED Talk. */ + char * winmmPathFull = NULL; char winmmPath[MAX_PATH] = {0}; GetSystemDirectory(winmmPath, MAX_PATH); - strcat_s(winmmPath, MAX_PATH, "\\winmm.dll"); + winmmPathFull = MwStringConcat(winmmPath, "\\winmm.dll"); MwLL_winmmLib = LoadLibraryA(winmmPath); MwLL_PFN_timeGetTime = (void *)GetProcAddress(MwLL_winmmLib, "timeGetTime"); MwLL_PFN_timeBeginPeriod = (void *)GetProcAddress(MwLL_winmmLib, "timeBeginPeriod"); From df1972e91c923dda68b01561d16c29ae299eb69a Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 10 Aug 2026 01:55:27 +0900 Subject: [PATCH 028/168] remove winmm --- CMakeLists.txt | 2 +- NTMakefile | 2 +- WatMakefile | 2 +- pl/ostype/Windows.pl | 1 - tools/genmk.pl | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b565a9..5441692 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -329,7 +329,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_SYSTEM_NAME STREQUAL "MSYS") PRIVATE USE_GDI ) - list(APPEND LIBRARIES gdi32 ole32 winmm uuid) + list(APPEND LIBRARIES gdi32 ole32 uuid) if(NOT MSVC) target_link_options( Mw diff --git a/NTMakefile b/NTMakefile index 8afa320..8f9a331 100644 --- a/NTMakefile +++ b/NTMakefile @@ -321,7 +321,7 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib winmm.lib ole32.lib user32.lib advapi32.lib + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index c2af03e..cbace36 100644 --- a/WatMakefile +++ b/WatMakefile @@ -320,7 +320,7 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/checkbox.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library winmm.lib library ole32.lib library user32.lib library advapi32.lib + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib diff --git a/pl/ostype/Windows.pl b/pl/ostype/Windows.pl index 9a066d8..e2ed1ab 100644 --- a/pl/ostype/Windows.pl +++ b/pl/ostype/Windows.pl @@ -4,7 +4,6 @@ $executable_suffix = ".exe"; $math = ""; add_ldflags("-Wl,--out-implib,src/libMw.dll.a -static-libgcc"); use_backend("gdi"); -add_libs("-lwinmm"); add_libs("-lole32"); add_libs("-luuid"); diff --git a/tools/genmk.pl b/tools/genmk.pl index 8362bd3..f0618e1 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -190,7 +190,7 @@ sub generate { print(OUT "src${dir}Mw.dll: " . cobjs($dir) . "\n"); print( OUT " \$(LD) \$(MW_LDFLAGS) $c_dllout $dllout\$@ " . cobjs($dir, $prefobj) - . " $needlibs ${lib}opengl32.lib ${lib}gdi32.lib ${lib}winmm.lib ${lib}ole32.lib ${lib}uuid.lib ${lib}user32.lib ${lib}advapi32.lib\n" + . " $needlibs ${lib}opengl32.lib ${lib}gdi32.lib ${lib}ole32.lib ${lib}uuid.lib ${lib}user32.lib ${lib}advapi32.lib\n" ); print(OUT " $c_dllafter\n"); print(OUT "\n"); From ca9a24a2b0e16382ef0bc2b9a187be279496982f Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 10 Aug 2026 04:32:44 +0900 Subject: [PATCH 029/168] watcom opengl fix --- NTMakefile | 2 +- WatMakefile | 2 +- src/core.c | 6 +----- tools/genmk.pl | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/NTMakefile b/NTMakefile index 8f9a331..63a4a2c 100644 --- a/NTMakefile +++ b/NTMakefile @@ -1,7 +1,7 @@ CC = cl /TC /c /nologo LD = link /nologo -MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT +MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL MW_LDFLAGS = /DLL EXE_CFLAGS = /Iinclude EXE_LDFLAGS = diff --git a/WatMakefile b/WatMakefile index cbace36..4533f3c 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,7 +1,7 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt diff --git a/src/core.c b/src/core.c index bc4645b..c27b1a6 100644 --- a/src/core.c +++ b/src/core.c @@ -1095,11 +1095,7 @@ int MwLibraryInit(void) { However, uhh, Visual Studio 2022. For some fucking reason. Thanks for coming to my TED Talk. */ - char * winmmPathFull = NULL; - char winmmPath[MAX_PATH] = {0}; - GetSystemDirectory(winmmPath, MAX_PATH); - winmmPathFull = MwStringConcat(winmmPath, "\\winmm.dll"); - MwLL_winmmLib = LoadLibraryA(winmmPath); + MwLL_winmmLib = LoadLibrary("winmm.dll"); MwLL_PFN_timeGetTime = (void *)GetProcAddress(MwLL_winmmLib, "timeGetTime"); MwLL_PFN_timeBeginPeriod = (void *)GetProcAddress(MwLL_winmmLib, "timeBeginPeriod"); diff --git a/tools/genmk.pl b/tools/genmk.pl index f0618e1..689e09e 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -116,7 +116,7 @@ sub generate { print(OUT "LD = $link\n"); print(OUT "\n"); print(OUT -"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT\n" +"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL\n" ); print(OUT "MW_LDFLAGS = $dll\n"); print(OUT "EXE_CFLAGS = ${inc}include\n"); From 2bea5634b618968593446f3ebf30f8f9a3cfc1b3 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 12 Sep 2026 04:15:02 +0900 Subject: [PATCH 030/168] fix bug --- examples/basic/filechooser.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/basic/filechooser.c b/examples/basic/filechooser.c index 2637f86..6a86f98 100644 --- a/examples/basic/filechooser.c +++ b/examples/basic/filechooser.c @@ -5,13 +5,17 @@ MwWidget window; MwWidget button; MwWidget mb; +#ifdef BUG MwBool fpicker_wait = MwFALSE; MwBool msgbox_wait = MwFALSE; +#endif void MWAPI ok(MwWidget handle, void* user, void* call) { (void)handle; (void)call; +#ifdef BUG msgbox_wait = MwFALSE; +#endif } void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { @@ -22,6 +26,7 @@ void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { MwAddUserHandler(MwMessageBoxGetChild(mb, MwMB_BUTTONOK), MwNactivateHandler, ok, mb); MwAddUserHandler(mb, MwNcloseHandler, ok, mb); +#ifdef BUG msgbox_wait = MwTRUE; while(msgbox_wait) { @@ -29,6 +34,7 @@ void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { } fpicker_wait = MwFALSE; +#endif } void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { @@ -42,6 +48,7 @@ void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { MwSetText(fpicker, MwNbackground, MwGetInteger(fpicker, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); +#ifdef BUG fpicker_wait = MwTRUE; while(fpicker_wait) { @@ -50,6 +57,7 @@ void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { MwDestroyWidget(fpicker); MwDestroyWidget(mb); +#endif } int main() { From 231df890c1e1f55e49747b76ceef56e68d066591 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 12:52:20 -0700 Subject: [PATCH 031/168] accidentally rounded MwU16 to MwU8 in color picker --- src/dialog/colorpicker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 95fc283..378b796 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -127,8 +127,8 @@ static void color_picker_image_update(color_picker_t* picker) { if(hue < 0.0) { hue += 360; } - hsv_v.h = (MwU8)((hue) * (HSV_HUE_STEPS / 360.)); - hsv_v.s = (MwU8)((dist) * (HSV_SAT_MAX / 180.)); + hsv_v.h = (MwU16)((hue) * (HSV_HUE_STEPS / 360.)); + hsv_v.s = (MwU16)((dist) * (HSV_SAT_MAX / 180.)); picker->hue_table[n] = hsv_v; picker->hue_table[n].generated = 1; } From 73833b9e0632fdc990f921214a25dc9cde2dc33a Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 12 Sep 2026 04:53:02 +0900 Subject: [PATCH 032/168] fix some colors --- examples/basic/colorpicker.c | 6 ++++-- examples/basic/filechooser.c | 4 +--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/basic/colorpicker.c b/examples/basic/colorpicker.c index dbce7fe..d02e357 100644 --- a/examples/basic/colorpicker.c +++ b/examples/basic/colorpicker.c @@ -35,12 +35,14 @@ int main() { window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL); - MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); + MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetText(window, MwNforeground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkForeground : MwDefaultForeground); button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "change window background", NULL); - MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); + MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetText(button, MwNforeground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkForeground : MwDefaultForeground); MwAddUserHandler(button, MwNactivateHandler, file_picker, NULL); diff --git a/examples/basic/filechooser.c b/examples/basic/filechooser.c index 6a86f98..6ad5636 100644 --- a/examples/basic/filechooser.c +++ b/examples/basic/filechooser.c @@ -64,13 +64,11 @@ int main() { MwLibraryInit(); window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, - MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL); - MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); + MwDEFAULT, 640, 480, MwNtitle, "file chooser", NULL); button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "select file", NULL); - MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); MwAddUserHandler(button, MwNactivateHandler, file_picker, NULL); From 2e9aca5d46de22027cdfb49f0f71d1027869db5e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 13:09:11 -0700 Subject: [PATCH 033/168] fix menu positioning under weston --- src/backend/wayland/wayland.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 839e9ac..087f48b 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -180,6 +180,9 @@ static void xdg_toplevel_configure(void* data, if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL) { if(width < 50) width = 50; if(height < 50) height = 50; + } else { + if(width < 1) width = 1; + if(height < 1) height = 1; } MwLLWaylandRegionInvalidate(self); @@ -281,7 +284,7 @@ static void setup_toplevel(MwLL r, int x, int y) { } /* check now if we have decorations so that everything else can act accordingly */ - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL && getenv("MW_FORCE_CSD") == NULL) { r->wayland.has_decorations = MwTRUE; } else { r->wayland.do_csd = MwTRUE; @@ -524,7 +527,7 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { } /* check now if we have decorations so that everything else can act accordingly */ - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL && getenv("MW_FORCE_CSD") == NULL) { r->wayland.has_decorations = MwTRUE; } else { r->wayland.do_csd = MwTRUE; @@ -537,10 +540,10 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { xdg_positioner_set_size(r->wayland.popup->xdg_positioner, r->wayland.ww, r->wayland.wh); xdg_positioner_set_anchor_rect( r->wayland.popup->xdg_positioner, - topmost_parent->wayland.x, topmost_parent->wayland.y, r->wayland.ww, r->wayland.wh); - xdg_positioner_set_offset( - r->wayland.popup->xdg_positioner, - r->wayland.x, r->wayland.y); + r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); + // xdg_positioner_set_offset( + // r->wayland.popup->xdg_positioner, + // r->wayland.x, r->wayland.y); xdg_positioner_set_anchor(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_NONE); xdg_positioner_set_gravity(r->wayland.popup->xdg_positioner, XDG_POSITIONER_GRAVITY_NONE); @@ -1120,6 +1123,9 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { if(w < 50) w = 50; if(h < 50) h = 50; + } else { + if(w < 1) w = 1; + if(h < 1) h = 1; } handle->wayland.ww = w; From 175827fd9b0bd588fed94d0f38fa627fe9e2f286 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 13:10:40 -0700 Subject: [PATCH 034/168] wayland: destroy popup surfaces at correct time --- src/backend/wayland/wayland.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 087f48b..34d2e13 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -584,14 +584,13 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { /* Popup destroy function */ static void destroy_popup(MwLL r) { - MwLLWaylandBackbufferDestroy(&r->wayland); MwLLWaylandFramebufferDestroy(&r->wayland); - xdg_surface_destroy(r->wayland.popup->xdg_surface); - xdg_popup_destroy(r->wayland.popup->xdg_popup); + xdg_surface_destroy(r->wayland.popup->xdg_surface); + xdg_positioner_destroy(r->wayland.popup->xdg_positioner); wl_surface_destroy(r->wayland.framebuffer.surface); From 117fa9cf925f11dcb27e14252827bc0f3a594002 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 12 Sep 2026 04:15:02 +0900 Subject: [PATCH 035/168] fix bug --- examples/basic/filechooser.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/basic/filechooser.c b/examples/basic/filechooser.c index 2637f86..6a86f98 100644 --- a/examples/basic/filechooser.c +++ b/examples/basic/filechooser.c @@ -5,13 +5,17 @@ MwWidget window; MwWidget button; MwWidget mb; +#ifdef BUG MwBool fpicker_wait = MwFALSE; MwBool msgbox_wait = MwFALSE; +#endif void MWAPI ok(MwWidget handle, void* user, void* call) { (void)handle; (void)call; +#ifdef BUG msgbox_wait = MwFALSE; +#endif } void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { @@ -22,6 +26,7 @@ void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { MwAddUserHandler(MwMessageBoxGetChild(mb, MwMB_BUTTONOK), MwNactivateHandler, ok, mb); MwAddUserHandler(mb, MwNcloseHandler, ok, mb); +#ifdef BUG msgbox_wait = MwTRUE; while(msgbox_wait) { @@ -29,6 +34,7 @@ void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { } fpicker_wait = MwFALSE; +#endif } void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { @@ -42,6 +48,7 @@ void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { MwSetText(fpicker, MwNbackground, MwGetInteger(fpicker, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); +#ifdef BUG fpicker_wait = MwTRUE; while(fpicker_wait) { @@ -50,6 +57,7 @@ void MWAPI file_picker(MwWidget handle, void* user_data, void* call_data) { MwDestroyWidget(fpicker); MwDestroyWidget(mb); +#endif } int main() { From b4545ed4e7b27bee997744c672a859910ab96928 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 12:52:20 -0700 Subject: [PATCH 036/168] accidentally rounded MwU16 to MwU8 in color picker --- src/dialog/colorpicker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 95fc283..378b796 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -127,8 +127,8 @@ static void color_picker_image_update(color_picker_t* picker) { if(hue < 0.0) { hue += 360; } - hsv_v.h = (MwU8)((hue) * (HSV_HUE_STEPS / 360.)); - hsv_v.s = (MwU8)((dist) * (HSV_SAT_MAX / 180.)); + hsv_v.h = (MwU16)((hue) * (HSV_HUE_STEPS / 360.)); + hsv_v.s = (MwU16)((dist) * (HSV_SAT_MAX / 180.)); picker->hue_table[n] = hsv_v; picker->hue_table[n].generated = 1; } From 846bf551be6bcb649dc1b75c424d63b98bb9099b Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 12 Sep 2026 04:53:02 +0900 Subject: [PATCH 037/168] fix some colors --- examples/basic/colorpicker.c | 6 ++++-- examples/basic/filechooser.c | 4 +--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/basic/colorpicker.c b/examples/basic/colorpicker.c index dbce7fe..d02e357 100644 --- a/examples/basic/colorpicker.c +++ b/examples/basic/colorpicker.c @@ -35,12 +35,14 @@ int main() { window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL); - MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); + MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetText(window, MwNforeground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkForeground : MwDefaultForeground); button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "change window background", NULL); - MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); + MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); + MwSetText(button, MwNforeground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultDarkForeground : MwDefaultForeground); MwAddUserHandler(button, MwNactivateHandler, file_picker, NULL); diff --git a/examples/basic/filechooser.c b/examples/basic/filechooser.c index 6a86f98..6ad5636 100644 --- a/examples/basic/filechooser.c +++ b/examples/basic/filechooser.c @@ -64,13 +64,11 @@ int main() { MwLibraryInit(); window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, - MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL); - MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); + MwDEFAULT, 640, 480, MwNtitle, "file chooser", NULL); button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "select file", NULL); - MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); MwAddUserHandler(button, MwNactivateHandler, file_picker, NULL); From b02698b940c50b2275123642b8b25ba28d690181 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 13:09:11 -0700 Subject: [PATCH 038/168] fix menu positioning under weston --- src/backend/wayland/wayland.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 839e9ac..087f48b 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -180,6 +180,9 @@ static void xdg_toplevel_configure(void* data, if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL) { if(width < 50) width = 50; if(height < 50) height = 50; + } else { + if(width < 1) width = 1; + if(height < 1) height = 1; } MwLLWaylandRegionInvalidate(self); @@ -281,7 +284,7 @@ static void setup_toplevel(MwLL r, int x, int y) { } /* check now if we have decorations so that everything else can act accordingly */ - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL && getenv("MW_FORCE_CSD") == NULL) { r->wayland.has_decorations = MwTRUE; } else { r->wayland.do_csd = MwTRUE; @@ -524,7 +527,7 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { } /* check now if we have decorations so that everything else can act accordingly */ - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL && getenv("MW_FORCE_CSD") == NULL) { r->wayland.has_decorations = MwTRUE; } else { r->wayland.do_csd = MwTRUE; @@ -537,10 +540,10 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { xdg_positioner_set_size(r->wayland.popup->xdg_positioner, r->wayland.ww, r->wayland.wh); xdg_positioner_set_anchor_rect( r->wayland.popup->xdg_positioner, - topmost_parent->wayland.x, topmost_parent->wayland.y, r->wayland.ww, r->wayland.wh); - xdg_positioner_set_offset( - r->wayland.popup->xdg_positioner, - r->wayland.x, r->wayland.y); + r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); + // xdg_positioner_set_offset( + // r->wayland.popup->xdg_positioner, + // r->wayland.x, r->wayland.y); xdg_positioner_set_anchor(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_NONE); xdg_positioner_set_gravity(r->wayland.popup->xdg_positioner, XDG_POSITIONER_GRAVITY_NONE); @@ -1120,6 +1123,9 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { if(w < 50) w = 50; if(h < 50) h = 50; + } else { + if(w < 1) w = 1; + if(h < 1) h = 1; } handle->wayland.ww = w; From 892f9198abe362fdac0ab0e878035a24c92f64af Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 13:10:40 -0700 Subject: [PATCH 039/168] wayland: destroy popup surfaces at correct time --- src/backend/wayland/wayland.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 087f48b..34d2e13 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -584,14 +584,13 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { /* Popup destroy function */ static void destroy_popup(MwLL r) { - MwLLWaylandBackbufferDestroy(&r->wayland); MwLLWaylandFramebufferDestroy(&r->wayland); - xdg_surface_destroy(r->wayland.popup->xdg_surface); - xdg_popup_destroy(r->wayland.popup->xdg_popup); + xdg_surface_destroy(r->wayland.popup->xdg_surface); + xdg_positioner_destroy(r->wayland.popup->xdg_positioner); wl_surface_destroy(r->wayland.framebuffer.surface); From 9246051de047dd10ffade7cd240c69714c535b85 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 13:31:37 -0700 Subject: [PATCH 040/168] new envs --- doc/ENV.md | 5 +++++ include/Mw/LowLevel.h | 11 ++++++++--- src/backend/wayland/wayland.c | 35 ++++++++++++++++++++++++----------- src/backend/x11.c | 30 ++++++++++++++++++++++-------- src/lowlevel.c | 18 +++++++++++++++--- 5 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 doc/ENV.md diff --git a/doc/ENV.md b/doc/ENV.md new file mode 100644 index 0000000..001c301 --- /dev/null +++ b/doc/ENV.md @@ -0,0 +1,5 @@ +Platforms that support both X11 and Wayland (Linux, namely) support launching Milsko programs with following environment variables: + +- `MW_BACKEND`: set to either `wayland` or `x11` to force which display protocol Wayland uses +- `MW_FORCE_CSD`: set to force the wayland backend to use CSD instead of SSD +- `MW_LIGHT_THEME`/`MW_DARK_THEME`: set to have either wayland or x11 ignore the system's appearence settings and either just use light theme/dark theme. diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 6647672..8822f68 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -41,6 +41,11 @@ struct _MwLLCommon { MwBool supports_transparency; MwLLHandler handler; + +#if defined(USE_WAYLAND) || defined(USE_X11) + /* 0 = default, 1 = light, 2 = dark */ + int theme_override; +#endif }; struct _MwLLCommonColor { @@ -364,9 +369,9 @@ MWDECL void* (*MwFLFontLoad)(unsigned char* data, unsigned int size, int px); MWDECL void (*MwFLFontFree)(void* handle); #ifdef _WIN32 -MWDECL void *MwLL_winmmLib; -MWDECL long (__stdcall* MwLL_PFN_timeGetTime)(void); -MWDECL unsigned int (__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); +MWDECL void* MwLL_winmmLib; +MWDECL long(__stdcall* MwLL_PFN_timeGetTime)(void); +MWDECL unsigned int(__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); #endif #ifdef __cplusplus diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 34d2e13..6d34e49 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -942,11 +942,13 @@ static void dark_theme_listener(MwLL handle, MwU32 new_value) { static void detect_dark_theme(MwLL handle) { MwU32 value = 0; - MwLLDBusPortalGet(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); - handle->wayland.dark_theme = (value == 1) ? 1 : 0; - - MwLLDBusPortalWatch(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings"); - + if(handle->common.theme_override != 0) { + handle->wayland.dark_theme = (handle->common.theme_override == 2) ? 1 : 0; + } else { + MwLLDBusPortalGet(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); + handle->wayland.dark_theme = (value == 1) ? 1 : 0; + MwLLDBusPortalWatch(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings"); + } MwLLDispatch(handle, dark_theme, &handle->wayland.dark_theme); } #endif @@ -1381,9 +1383,8 @@ static int MwLLPendingImpl(MwLL handle) { } #ifdef USE_DBUS - if(wl_call_tbl.has_dbus) { + if(wl_call_tbl.has_dbus || handle->common.theme_override == 0) { if(handle->wayland.dark_theme_detection) { - handle->wayland.dark_theme_detection = MwFALSE; detect_dark_theme(handle); MwLLDispatch(handle, draw, NULL); @@ -1907,10 +1908,22 @@ static void MwLLClipImpl(MwLL handle, MwRect* rect) { static int MwLLWaylandCallInitImpl(void) { #ifdef __linux__ - MwBool loadWayland = MwFALSE; - if(getenv("MILSKO_BACKEND")) { - loadWayland |= - (strcmp(getenv("MILSKO_BACKEND"), "wayland") == 0); + MwBool loadWayland = MwFALSE; + char* milsko_backend_env = getenv("MILSKO_BACKEND"); + char* mw_backend_env = getenv("MW_BACKEND"); + + if(milsko_backend_env || mw_backend_env) { + if(milsko_backend_env) { + /* + * (deprecated since 1.5+ but we have no reason to ever remove the old variable. + * MW_BACKEND is just the one that's documented) + */ + printf("[WARNING] MILSKO_BACKEND env is deprecated, use MW_BACKEND instead.\n"); + loadWayland |= (strcmp(milsko_backend_env, "wayland") == 0); + } else { + loadWayland |= (strcmp(mw_backend_env, "wayland") == 0); + } + } else if(getenv("WAYLAND_DISPLAY")) { loadWayland |= (getenv("WAYLAND_DISPLAY") != NULL); } diff --git a/src/backend/x11.c b/src/backend/x11.c index cc4d22b..8b908e4 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -327,9 +327,12 @@ static XVisualInfo* get_visual_info(Display* display) { static void detect_dark_theme(MwLL handle) { MwU32 value = 0; MwU32 dark_theme = 0; - MwLLDBusPortalGet(&xsymtbl.dbus, &handle->x11.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); - - dark_theme = (value == 1) ? 1 : 0; + if(handle->common.theme_override != 0) { + dark_theme = (handle->common.theme_override == 2) ? 1 : 0; + } else { + MwLLDBusPortalGet(&xsymtbl.dbus, &handle->x11.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); + dark_theme = (value == 1) ? 1 : 0; + } MwLLDispatch(handle, dark_theme, &dark_theme); } @@ -652,7 +655,7 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->x11.dark_theme_detection) { handle->x11.dark_theme_detection = MwFALSE; #ifdef USE_DBUS - if(xsymtbl.has_dbus) { + if(xsymtbl.has_dbus || handle->common.theme_override == 0) { detect_dark_theme(handle); MwLLDispatch(handle, draw, NULL); } @@ -1403,10 +1406,21 @@ static void MwLLClipImpl(MwLL handle, MwRect* rect) { } static int MwLLX11CallInitImpl(void) { - MwBool loadX11 = MwFALSE; - if(getenv("MILSKO_BACKEND")) { - loadX11 |= - (strcmp(getenv("MILSKO_BACKEND"), "x11") == 0); + MwBool loadX11 = MwFALSE; + char* milsko_backend_env = getenv("MILSKO_BACKEND"); + char* mw_backend_env = getenv("MW_BACKEND"); + + if(milsko_backend_env || mw_backend_env) { + if(milsko_backend_env) { + /* + * (deprecated since 1.5+ but we have no reason to ever remove the old variable. + * MW_BACKEND is just the one that's documented) + */ + printf("[WARNING] MILSKO_BACKEND env is deprecated, use MW_BACKEND instead.\n"); + loadX11 |= (strcmp(milsko_backend_env, "x11") == 0); + } else { + loadX11 |= (strcmp(mw_backend_env, "x11") == 0); + } } else if(getenv("DISPLAY")) { loadX11 |= (getenv("DISPLAY") != NULL); } diff --git a/src/lowlevel.c b/src/lowlevel.c index 2fe1535..32070d9 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -1,9 +1,9 @@ #include #ifdef _WIN32 -void *MwLL_winmmLib; -long (__stdcall* MwLL_PFN_timeGetTime)(void); -unsigned int (__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); +void* MwLL_winmmLib; +long(__stdcall* MwLL_PFN_timeGetTime)(void); +unsigned int(__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); #endif MwLL (*MwLLCreate)(MwLL parent, int x, int y, int width, int height) = NULL; @@ -66,10 +66,22 @@ void (*MwLLRaise)(MwLL handle) = NULL; void (*MwLLClip)(MwLL handle, MwRect* rect) = NULL; void MwLLCreateCommon(MwLL handle) { +#if defined(USE_WAYLAND) || defined(USE_X11) + char* light_theme = getenv("MW_LIGHT_THEME"); + char* dark_theme = getenv("MW_DARK_THEME"); +#endif + handle->common.handler = malloc(sizeof(*handle->common.handler)); memset(handle->common.handler, 0, sizeof(*handle->common.handler)); handle->common.supports_transparency = 0; + +#if defined(USE_WAYLAND) || defined(USE_X11) + if(light_theme || dark_theme) { + handle->common.theme_override = (light_theme != NULL) ? 1 : ((dark_theme != NULL) ? 2 : 0); + } + +#endif } void MwLLDestroyCommon(MwLL handle) { From 292ffe1120a65a57f13b7576aa1132dbbbc0c7f9 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 13:38:58 -0700 Subject: [PATCH 041/168] more robust mw_force_csd --- src/backend/wayland/wayland.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 6d34e49..82c053e 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -171,10 +171,6 @@ static void xdg_toplevel_configure(void* data, if(width == 0 || height == 0) { width = self->wayland.ww; height = self->wayland.wh; - /* if it's still 0 then bail */ - if(width == 0 || height == 0) { - return; - } } if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL) { @@ -257,6 +253,7 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { /* Toplevel setup function */ static void setup_toplevel(MwLL r, int x, int y) { + char* mw_force_csd = getenv("MW_FORCE_CSD"); r->wayland.type = MwLL_WAYLAND_TOPLEVEL; r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); r->wayland.x = x; @@ -284,7 +281,10 @@ static void setup_toplevel(MwLL r, int x, int y) { } /* check now if we have decorations so that everything else can act accordingly */ - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL && getenv("MW_FORCE_CSD") == NULL) { + if(mw_force_csd != NULL) { + r->wayland.has_decorations = strcmp(mw_force_csd, "0") == 0; + r->wayland.do_csd = strcmp(mw_force_csd, "1") == 0; + } else if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { r->wayland.has_decorations = MwTRUE; } else { r->wayland.do_csd = MwTRUE; @@ -492,11 +492,12 @@ struct xdg_popup_listener popup_listener = { /* Popup setup function */ static void setup_popup(MwLL r, int x, int y, MwLL parent) { - MwLL topmost_parent = r->wayland.parent; - r->wayland.type = MwLL_WAYLAND_POPUP; - r->wayland.x = x; - r->wayland.y = y; - r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); + char* mw_force_csd = getenv("MW_FORCE_CSD"); + MwLL topmost_parent = r->wayland.parent; + r->wayland.type = MwLL_WAYLAND_POPUP; + r->wayland.x = x; + r->wayland.y = y; + r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); if(parent) { MwWidget p = parent->common.user; @@ -527,7 +528,10 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { } /* check now if we have decorations so that everything else can act accordingly */ - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL && getenv("MW_FORCE_CSD") == NULL) { + if(mw_force_csd != NULL) { + r->wayland.has_decorations = strcmp(mw_force_csd, "0") == 0; + r->wayland.do_csd = strcmp(mw_force_csd, "1") == 0; + } else if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { r->wayland.has_decorations = MwTRUE; } else { r->wayland.do_csd = MwTRUE; From 77e652cddccb5571e59bd18d6930d833485ef98b Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 12 Sep 2026 06:34:35 +0900 Subject: [PATCH 042/168] improve checkbox --- src/abstract/directory.c | 12 ++++++------ src/core.c | 8 ++++---- src/draw.c | 6 +++--- src/string.c | 6 ++---- src/widget/checkbox.c | 40 ++++++++++++++++++++++++++++++++++++---- 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/abstract/directory.c b/src/abstract/directory.c index ddf10e1..3fbc235 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -19,8 +19,8 @@ typedef struct dir { void* MwDirectoryOpen(const char* path) { dir_t* dir = malloc(sizeof(*dir)); - char * p; - if(!dir) { + char* p; + if(!dir) { printf("Out Of Memory\n"); return NULL; } @@ -70,15 +70,15 @@ MwDirectoryEntry* MwDirectoryRead(void* handle) { dir_t* dir = handle; MwDirectoryEntry* entry = malloc(sizeof(*entry)); #ifdef _WIN32 - ULARGE_INTEGER* l; + ULARGE_INTEGER* l; #elif defined(CLASSIC_MAC_OS) #else - struct dirent* d; + struct dirent* d; struct stat s; char* p; #endif - - if(!entry) { + + if(!entry) { printf("Out Of Memory\n"); return NULL; } diff --git a/src/core.c b/src/core.c index c27b1a6..3180922 100644 --- a/src/core.c +++ b/src/core.c @@ -1090,14 +1090,14 @@ int MwLibraryInit(void) { int i; #ifdef _WIN32 - /* + /* There's no Windows configuration that Milsko supports that doesn't have winmm. However, uhh, Visual Studio 2022. For some fucking reason. Thanks for coming to my TED Talk. */ - MwLL_winmmLib = LoadLibrary("winmm.dll"); - MwLL_PFN_timeGetTime = (void *)GetProcAddress(MwLL_winmmLib, "timeGetTime"); - MwLL_PFN_timeBeginPeriod = (void *)GetProcAddress(MwLL_winmmLib, "timeBeginPeriod"); + MwLL_winmmLib = LoadLibrary("winmm.dll"); + MwLL_PFN_timeGetTime = (void*)GetProcAddress(MwLL_winmmLib, "timeGetTime"); + MwLL_PFN_timeBeginPeriod = (void*)GetProcAddress(MwLL_winmmLib, "timeBeginPeriod"); MwLL_PFN_timeBeginPeriod(10); #endif diff --git a/src/draw.c b/src/draw.c index 2314c02..c6de78f 100644 --- a/src/draw.c +++ b/src/draw.c @@ -124,7 +124,7 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { int ColorDiff = get_color_diff(handle); double darkenStep = (ColorDiff / 2.) / rect->height; unsigned long sz = 1 * rect->height * 4; - unsigned char* data = malloc(sz*2); + unsigned char* data = malloc(sz * 2); MwRect r = *rect; if(!data) { return; @@ -952,8 +952,8 @@ MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { } } - rgb = malloc(row * col * 4); - comp = malloc(cpp + 1); + rgb = malloc(row * col * 4); + comp = malloc(cpp + 1); if(!rgb || !comp) { printf("Null malloc! Out of memory?"); return NULL; diff --git a/src/string.c b/src/string.c index c894b9a..579c57e 100644 --- a/src/string.c +++ b/src/string.c @@ -2,7 +2,7 @@ char* MwStringDuplicate(const char* str) { int sz = strlen(str) + 1; - char* r = malloc(sz); + char* r = malloc(sz); if(!r) { printf("Out Of Memory\n"); return NULL; @@ -19,7 +19,7 @@ char* MwStringDuplicate(const char* str) { char* MwStringConcat(const char* str1, const char* str2) { int sz = strlen(str1) + strlen(str2) + 1; - char* r = malloc(sz); + char* r = malloc(sz); if(!r) { printf("Out Of Memory\n"); return NULL; @@ -64,8 +64,6 @@ void MwStringTime(char* out, time_t t) { struct tm* tm = localtime(&t); const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - - if(tm == NULL) { #if defined(_MSC_VER) && (_MSC_VER >= 1400) sprintf_s(out, 255, "localtime error"); diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index f196954..8e65dc0 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -10,8 +10,10 @@ static int wcreate(MwWidget handle) { static void draw(MwWidget handle) { MwRect r; - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwLLColor base2 = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); + MwLLColor text2 = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; @@ -27,12 +29,42 @@ static void draw(MwWidget handle) { r.x = (MwGetInteger(handle, MwNwidth) - r.width) / 2; r.y = (MwGetInteger(handle, MwNheight) - r.height) / 2; - MwDrawWidgetBack(handle, &r, base, (handle->pressed || MwGetInteger(handle, MwNchecked)) ? 1 : 0, MwDEFAULT); + MwDrawFrame(handle, &r, base, 1); + MwDrawRect(handle, &r, base2); if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); if(handle->pressed || MwGetInteger(handle, MwNchecked)) { - /* TODO: write check mark */ + MwPoint p[6]; + int gap_w = r.width / 4 / 3; + int gap_h = r.height / 4 / 3; + + r.x += gap_w; + r.y += gap_h; + r.width -= gap_w * 2; + r.height -= gap_h * 2; + + p[0].x = r.x; + p[0].y = r.y + r.height * 2 / 3; + + p[1].x = r.x + r.width / 3; + p[1].y = r.y + r.height; + + p[2].x = r.x + r.width; + p[2].y = r.y + r.height / 3; + + p[3] = p[2]; + p[3].y -= r.height / 3; + + p[4] = p[1]; + p[4].y -= r.height / 3; + + p[5] = p[0]; + p[5].y -= r.height / 3; + + MwLLPolygon(handle->lowlevel, p, 6, text2); } + MwLLFreeColor(text2); + MwLLFreeColor(base2); MwLLFreeColor(base); } From eb1db3a5e97aa1c115a2a3e22bde341c261774c5 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 12 Sep 2026 06:45:45 +0900 Subject: [PATCH 043/168] fix MwDirectoryOpen --- src/abstract/directory.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/abstract/directory.c b/src/abstract/directory.c index 3fbc235..977f2f5 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -25,13 +25,15 @@ void* MwDirectoryOpen(const char* path) { return NULL; } #ifdef _WIN32 - p = MwStringDuplicate(path); + p = malloc(strlen(path) + 2 + 1); + + strcpy(p, path); if(strchr(path, '/') != NULL) { - MwStringConcat(p, "/"); + strcat(p, "/"); } else { - MwStringConcat(p, "\\"); + strcat(p, "\\"); } - MwStringConcat(p, "*"); + strcat(p, "*"); if((dir->hFind = FindFirstFile(p, &dir->ffd)) == INVALID_HANDLE_VALUE) { free(p); free(dir); From 806ce3b8643007510608bee2c15ee20e975f0157 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 16:22:43 -0700 Subject: [PATCH 044/168] radioboxes --- examples/basic/periodic.c | 3 +- include/Mw/Draw.h | 11 ++++ include/Mw/TypeDefs.h | 1 + src/draw.c | 103 ++++++++++++++++++++++++++++++++++++-- src/widget/radiobox.c | 75 ++++++++++++++++++++------- 5 files changed, 170 insertions(+), 23 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index 92dab70..b449f09 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -237,8 +237,7 @@ int main() { sprintf(buf, "%sBox %d", i == 0 ? "Check" : "Radio", j + 1); MwVaCreateWidget(MwLabelClass, "label", b, 0, 0, 0, 0, MwNtext, buf, - MwNalignment, MwALIGNMENT_BEGINNING, - NULL); + MwNalignment, MwALIGNMENT_BEGINNING, MwNdisabled, (j == 5) ? 1 : 0, NULL); } } diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index deefe0f..443835c 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -187,6 +187,17 @@ MWDECL MwLLPixmap MWAPI MwLoadIcon(MwWidget handle, MwU32* data); */ MWDECL void MWAPI MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert); +/*! + * @brief Draws a circle + * @param handle Widget + * @param rect Rectangle area + * @param color Color + * @param color Background to fade to; widget background used if NULL + * @param filled Fill the circle or not + * @param outward + */ +MWDECL void MWAPI MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor background, int filled); + /* text.c */ /*! diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index ad072a3..a9bc3cf 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -92,6 +92,7 @@ struct _MwWidget { MwPoint mouse_point; int close; int prop_event; + int held; void* internal; void* opaque; diff --git a/src/draw.c b/src/draw.c index 2314c02..c7869e0 100644 --- a/src/draw.c +++ b/src/draw.c @@ -124,7 +124,7 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { int ColorDiff = get_color_diff(handle); double darkenStep = (ColorDiff / 2.) / rect->height; unsigned long sz = 1 * rect->height * 4; - unsigned char* data = malloc(sz*2); + unsigned char* data = malloc(sz * 2); MwRect r = *rect; if(!data) { return; @@ -303,6 +303,103 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { MwLLFreeColor(darker); } +void MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor background, int filled) { + MwLLPixmap pixmap; + int width = rect->width; + int height = rect->height; + unsigned long sz = (unsigned long)width * height * 4; + unsigned char* data; + double cx, cy, rx, ry; + int border; + int x, y; + int ColorDiff = (get_color_diff(handle)); + MwLLColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); + MwLLColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); + MwLLColor base = MwLightenColor(handle, color, 0, 0, 0); + + color_set_disabled_if_disabled(handle, darker); + color_set_disabled_if_disabled(handle, lighter); + color_set_disabled_if_disabled(handle, base); + + if(width <= 0 || height <= 0) return; + + data = malloc(sz); + if(!data) return; + memset(data, 0, sz); + + cx = width / 2.0; + cy = height / 2.0; + rx = width / 2.0; + ry = height / 2.0; + border = filled ? 0 : MwDefaultBorderWidth(handle); + + for(y = 0; y < height; y++) { + for(x = 0; x < width; x++) { + double nx = (x + 0.5 - cx) / rx; + double ny = (y + 0.5 - cy) / ry; + double dist = nx * nx + ny * ny; + int inside; + double inx = (x + 0.5 - cx) / (rx - border); + double iny = (y + 0.5 - cy) / (ry - border); + double innerDist = inx * inx + iny * iny; + if(filled) { + inside = dist <= 1.0; + } else if(rx > border && ry > border) { + inside = dist <= 1.0 && innerDist > 1.0; + } else { + inside = dist <= 1.0; + } + + if(inside) { + MwLLColor mixColor; + MwLLColor c = background ? background : (handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground))); + double mod; + unsigned char* pout = &data[(y * width + x) * 4]; + + if(MwGetInteger(handle, MwNdarkTheme)) { + mixColor = MwLightenColor(handle, base, -ColorDiff, -ColorDiff, -ColorDiff); + } else { + mixColor = MwLightenColor(handle, base, ColorDiff, ColorDiff, ColorDiff); + } + + if(MwGetInteger(handle, MwNdisabled)) { + mod = (innerDist * 2.) - 1; + } else { + mod = (innerDist / 2.) + 0.5; + } + color_set_disabled_if_disabled(handle, mixColor); + + if(c != NULL) { + mixColor->common.red = (MwU8)(mixColor->common.red + (c->common.red - mixColor->common.red) * mod); + mixColor->common.green = (MwU8)(mixColor->common.green + (c->common.green - mixColor->common.green) * mod); + mixColor->common.blue = (MwU8)(mixColor->common.blue + (c->common.blue - mixColor->common.blue) * mod); + MwLLColorUpdate(handle->lowlevel, mixColor, mixColor->common.red, mixColor->common.green, mixColor->common.blue); + + if(c != background) { + MwLLFreeColor(c); + } + } + + pout[0] = (MwU8)mixColor->common.red; + pout[1] = (MwU8)mixColor->common.green; + pout[2] = (MwU8)mixColor->common.blue; + + pout[3] = 255; + } + } + } + + pixmap = MwLLCreatePixmap(handle->lowlevel, data, width, height); + MwLLDrawPixmap(handle->lowlevel, rect, pixmap); + MwLLDestroyPixmap(pixmap); + + MwLLFreeColor(lighter); + MwLLFreeColor(darker); + MwLLFreeColor(base); + + free(data); +}; + static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { MwPoint p[7]; int ColorDiff = get_color_diff(handle); @@ -952,8 +1049,8 @@ MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { } } - rgb = malloc(row * col * 4); - comp = malloc(cpp + 1); + rgb = malloc(row * col * 4); + comp = malloc(cpp + 1); if(!rgb || !comp) { printf("Null malloc! Out of memory?"); return NULL; diff --git a/src/widget/radiobox.c b/src/widget/radiobox.c index c93e054..1930259 100644 --- a/src/widget/radiobox.c +++ b/src/widget/radiobox.c @@ -30,7 +30,37 @@ static void draw(MwWidget handle) { r.x = (MwGetInteger(handle, MwNwidth) - r.width) / 2; r.y = (MwGetInteger(handle, MwNheight) - r.height) / 2; - MwDrawDiamond(handle, &r, base, (handle->pressed || MwGetInteger(handle, MwNchecked)) ? 1 : 0); + if(MwGetInteger(handle, MwNmodernLook) == 1) { + int is_checked = (handle->pressed || MwGetInteger(handle, MwNchecked)); + MwLLColor darker; + MwLLColor inner; + MwLLColor innerunsel = base; + + if(MwGetInteger(handle, MwNdarkTheme) == 1) { + darker = MwLLAllocColor(handle->lowlevel, 255, 255, 255); + innerunsel = MwLightenColor(handle, base, 80, 80, 80); + inner = darker; + } else { + darker = MwLLAllocColor(handle->lowlevel, 0, 0, 0); + inner = MwLightenColor(handle, is_checked ? darker : base, -80, -80, -80); + } + MwDrawCircle(handle, &r, darker, NULL, 1); + + if(!MwGetInteger(handle, MwNdisabled)) { + r.x += 2; + r.y += 2; + r.width -= 4; + r.height -= 4; + if(!is_checked) { + MwDrawCircle(handle, &r, innerunsel, innerunsel, 1); + } else { + MwDrawCircle(handle, &r, inner, innerunsel, 1); + } + } + MwLLFreeColor(darker); + } else { + MwDrawDiamond(handle, &r, base, (handle->pressed || MwGetInteger(handle, MwNchecked)) ? 1 : 0); + } MwLLFreeColor(base); } @@ -49,29 +79,38 @@ static void click(MwWidget handle) { MwDispatchUserHandler(handle, MwNchangedHandler, NULL); } +static void mouse_down(MwWidget handle, void* ptr) { + handle->held = 1; + MwForceRender2(handle, ptr); +} + +static void mouse_up(MwWidget handle, void* ptr) { + handle->held = 0; + MwForceRender2(handle, ptr); +} static void prop_change(MwWidget handle, const char* key) { if(strcmp(key, MwNchecked) == 0) MwForceRender(handle); } MwClassRec MwRadioBoxClassRec = { - wcreate, /* create */ - NULL, /* destroy */ - draw, /* draw */ - click, /* click */ - NULL, /* parent_resize */ - prop_change, /* prop_change */ - NULL, /* mouse_move */ - MwForceRender2, /* mouse_up */ - MwForceRender2, /* mouse_down */ - NULL, /* key */ - NULL, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ + wcreate, /* create */ + NULL, /* destroy */ + draw, /* draw */ + click, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + mouse_up, /* mouse_up */ + mouse_down, /* mouse_down */ + NULL, /* key */ + NULL, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ NULL, NULL, NULL}; From 5479cb3e307333bb82594fc44159f5e763f29e88 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 18:05:42 -0700 Subject: [PATCH 045/168] fix for hyprland that should go away very quickly --- CMakeLists.txt | 5 +- include/Mw/LowLevel/Wayland.h | 7 + pl/rules.pl | 4 +- src/backend/wayland/hyprland.c | 60 ++++++ src/backend/wayland/interfaces.c | 8 +- src/draw.c | 353 ++++++++++++++++++++++++------- 6 files changed, 358 insertions(+), 79 deletions(-) create mode 100644 src/backend/wayland/hyprland.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5441692..d072daf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,6 +269,7 @@ if(MW_USE_WAYLAND) src/backend/cairo.c src/backend/wayland/wayland.c src/backend/wayland/buffer.c + src/backend/wayland/hyprland.c src/backend/wayland/interfaces.c src/backend/wayland/region.c ) @@ -331,7 +332,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_SYSTEM_NAME STREQUAL "MSYS") ) list(APPEND LIBRARIES gdi32 ole32 uuid) if(NOT MSVC) - target_link_options( + target_link_options( Mw PRIVATE -static-libgcc @@ -468,7 +469,7 @@ if(MW_BUILD_VULKAN) check_include_files(vulkan/VULKAN.h HAS_VK_HEADER) if(HAS_VK_HEADER) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE MW_VULKAN diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index ccd1f2f..0f570e3 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -454,6 +454,8 @@ struct _MwLLWayland { MwU64 next_elapsed; long start_time; long end_time; + + MwBool on_hyprland; }; struct _MwLLWaylandColor { @@ -479,6 +481,11 @@ void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer); void MwLLWaylandRegionSetup(MwLL handle); void MwLLWaylandRegionInvalidate(MwLL handle); +int MwLLWaylandDoRoundness(MwLL handle); + +/* Reads the "roundness" value out of ~/.config/hypr/hyprland.lua, or returns `fallback` if unavailable. */ +int MwLLWaylandHyprlandGetRoundness(void); + void MwLLWaylandHangUntilConfigured(MwLL handle); MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); diff --git a/pl/rules.pl b/pl/rules.pl index 89f13e9..80f930d 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -49,6 +49,7 @@ if (grep(/^wayland$/, @backends)) { new_object("src/backend/cairo.c"); new_object("src/backend/wayland/wayland.c"); new_object("src/backend/wayland/buffer.c"); + new_object("src/backend/wayland/hyprland.c"); new_object("src/backend/wayland/interfaces.c"); new_object("src/backend/wayland/region.c"); @@ -66,8 +67,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); - scan_wayland_protocol_from_file("wlr-layer-shell", - "wlr-layer-shell-unstable-v1.xml"); + scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); $gl_libs = "-lGL -lGLU"; } diff --git a/src/backend/wayland/hyprland.c b/src/backend/wayland/hyprland.c new file mode 100644 index 0000000..e6c8679 --- /dev/null +++ b/src/backend/wayland/hyprland.c @@ -0,0 +1,60 @@ +#include + +int MwLLWaylandDoRoundness(MwLL handle) { + if(handle->common.type == MwLLBackendWayland) { + return handle->wayland.on_hyprland; + } else { + return 0; + }; +}; + +int MwLLWaylandHyprlandGetRoundness(void) { + char* home = getenv("HOME"); + int fallback = 20; + char path[PATH_MAX]; + int roundness = fallback; + char line[512]; + FILE* f = NULL; + + if(home == NULL) { + return fallback; + } + + snprintf(path, sizeof(path), "%s/.config/hypr/hyprland.lua", home); + + f = fopen(path, "r"); + if(f == NULL) { + return fallback; + } + + while(fgets(line, sizeof(line), f) != NULL) { + char* key = strstr(line, "roundness"); + char* eq; + char* end; + long value; + + if(key == NULL) { + continue; + } + + eq = strchr(key, '='); + if(eq == NULL) { + continue; + } + eq++; + + while(*eq != '\0' && isspace((unsigned char)*eq)) { + eq++; + } + + value = strtol(eq, &end, 10); + if(end == eq) { + continue; + } + + roundness = (int)value; + } + + fclose(f); + return roundness; +} diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 84ed492..a724591 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -40,15 +40,19 @@ static void new_protocol(void* data, struct wl_registry* registry, MwLL self = data; (void)version; (void)registry; + wayland_protocol_callback_table_t* cb; WAYLAND_EVENT_OP_START(self); - wayland_protocol_callback_table_t* cb = shget(self->wayland.wl_protocol_setup_map, interface); + cb = shget(self->wayland.wl_protocol_setup_map, interface); if(cb != NULL) { shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data, version)); - /* we don't care for adding this protocol, we just use it to know if the compositor will let us have transparent surfaces */ } else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) { + /* we don't care for adding this protocol, we just use it to know if the compositor will let us have transparent surfaces */ self->common.supports_transparency = MwTRUE; + } else if(strstr(interface, "hyprland") != NULL) { + /* we have nothing to make use of with hyprland, we just want to check if we're running under it. */ + self->wayland.on_hyprland = MwTRUE; } else { // printf("unknown interface %s\n", interface); } diff --git a/src/draw.c b/src/draw.c index c7869e0..19b4081 100644 --- a/src/draw.c +++ b/src/draw.c @@ -53,6 +53,105 @@ static void color_set_disabled_if_disabled(MwWidget handle, MwLLColor rgb) { } }; +/* Whether (x, y) within a w*h rect falls inside a rounded-rect mask of the + * given corner radius. Shared by every raster-based rounded fill below so + * they all cut the same corner shape. */ +static int rounded_rect_contains(int x, int y, int w, int h, int rad) { + int cx = -1; + int cy = -1; + + if(x < rad && y < rad) { + cx = rad; + cy = rad; + } else if(x >= w - rad && y < rad) { + cx = w - rad - 1; + cy = rad; + } else if(x < rad && y >= h - rad) { + cx = rad; + cy = h - rad - 1; + } else if(x >= w - rad && y >= h - rad) { + cx = w - rad - 1; + cy = h - rad - 1; + } + + if(cx < 0) { + return 1; + } + + { + int dx = x - cx; + int dy = y - cy; + return (dx * dx + dy * dy) <= rad * rad; + } +} + +static void fill_rect(MwWidget handle, MwRect* rect, MwLLColor color) { + MwPoint p[4]; + + p[0].x = rect->x; + p[0].y = rect->y; + + p[1].x = rect->x + rect->width; + p[1].y = rect->y; + + p[2].x = rect->x + rect->width; + p[2].y = rect->y + rect->height; + + p[3].x = rect->x; + p[3].y = rect->y + rect->height; + + MwLLPolygon(handle->lowlevel, p, 4, color); +} + +/* Flat-colored rounded-rect fill, for backdrops that need to match a rounded + * border/fill's shape instead of a plain MwDrawRect square. */ +static void fill_rect_rounded(MwWidget handle, MwRect* rect, MwLLColor color, int roundness) { + MwLLPixmap pixmap; + int x, y; + int w = rect->width; + int h = rect->height; + int rad = roundness; + unsigned char* data; + + if(w <= 0 || h <= 0) { + return; + } + + if(rad > w / 2) rad = w / 2; + if(rad > h / 2) rad = h / 2; + + if(rad <= 0) { + fill_rect(handle, rect, color); + return; + } + + data = malloc((unsigned long)w * h * 4); + if(!data) { + return; + } + + memset(data, 0, (unsigned long)w * h * 4); + + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + if(rounded_rect_contains(x, y, w, h, rad)) { + unsigned char* pout = &data[(y * w + x) * 4]; + + pout[0] = (unsigned char)color->common.red; + pout[1] = (unsigned char)color->common.green; + pout[2] = (unsigned char)color->common.blue; + pout[3] = 255; + } + } + } + + pixmap = MwLLCreatePixmap(handle->lowlevel, data, w, h); + MwLLDrawPixmap(handle->lowlevel, rect, pixmap); + MwLLDestroyPixmap(pixmap); + + free(data); +} + void MwParseColorNoAllocate(const char* text, MwRGB* rgb) { if(text[0] == '#' && strlen(text) == 4) { rgb->red = hex(text + 1, 1); @@ -100,63 +199,104 @@ MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b) } void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { - MwPoint p[4]; - - p[0].x = rect->x; - p[0].y = rect->y; - - p[1].x = rect->x + rect->width; - p[1].y = rect->y; - - p[2].x = rect->x + rect->width; - p[2].y = rect->y + rect->height; - - p[3].x = rect->x; - p[3].y = rect->y + rect->height; - - MwLLPolygon(handle->lowlevel, p, 4, color); + if(MwLLWaylandDoRoundness(handle->lowlevel)) { + fill_rect_rounded(handle, rect, color, MwLLWaylandHyprlandGetRoundness()); + } else { + fill_rect(handle, rect, color); + } } void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { - MwLLPixmap pixmap; - int y; - double darken = 0.; - int ColorDiff = get_color_diff(handle); - double darkenStep = (ColorDiff / 2.) / rect->height; - unsigned long sz = 1 * rect->height * 4; - unsigned char* data = malloc(sz * 2); - MwRect r = *rect; - if(!data) { - return; - } + MwLLPixmap pixmap; + int y; + double darken = 0.; + int ColorDiff = get_color_diff(handle); + MwRect r = *rect; + int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; + if(rect->width <= 0 || rect->height <= 0) { - free(data); return; } - memset(data, 0, sz); r.x += 1; r.y += 1; r.width -= 2; r.height -= 2; - for(y = 0; y < rect->height; y++) { - MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); - int idx = y * 4; - color_set_disabled_if_disabled(handle, col); - data[idx] = col->common.red; - data[idx + 1] = col->common.green; - data[idx + 2] = col->common.blue; - data[idx + 3] = 255; - MwLLFreeColor(col); - darken += darkenStep; + if(r.width <= 0 || r.height <= 0) { + return; } - pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); - MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - MwLLDestroyPixmap(pixmap); + if(roundness <= 0) { + double darkenStep = (ColorDiff / 2.) / rect->height; + unsigned long sz = 1 * rect->height * 4; + unsigned char* data = malloc(sz * 2); + if(!data) { + return; + } + memset(data, 0, sz); - free(data); + for(y = 0; y < rect->height; y++) { + MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); + int idx = y * 4; + color_set_disabled_if_disabled(handle, col); + data[idx] = col->common.red; + data[idx + 1] = col->common.green; + data[idx + 2] = col->common.blue; + data[idx + 3] = 255; + MwLLFreeColor(col); + darken += darkenStep; + } + + pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + MwLLDestroyPixmap(pixmap); + + free(data); + return; + } else { + int w = r.width; + int h = r.height; + int rad = roundness; + int x; + double darkenStep; + unsigned char* data; + + if(rad > w / 2) rad = w / 2; + if(rad > h / 2) rad = h / 2; + + darkenStep = (ColorDiff / 2.) / h; + data = malloc((unsigned long)w * h * 4); + if(!data) { + return; + } + memset(data, 0, (unsigned long)w * h * 4); + + for(y = 0; y < h; y++) { + MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); + color_set_disabled_if_disabled(handle, col); + + for(x = 0; x < w; x++) { + if(rounded_rect_contains(x, y, w, h, rad)) { + unsigned char* pout = &data[(y * w + x) * 4]; + + pout[0] = (unsigned char)col->common.red; + pout[1] = (unsigned char)col->common.green; + pout[2] = (unsigned char)col->common.blue; + pout[3] = 255; + } + } + + MwLLFreeColor(col); + darken += darkenStep; + } + + pixmap = MwLLCreatePixmap(handle->lowlevel, data, w, h); + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + MwLLDestroyPixmap(pixmap); + + free(data); + } } void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { @@ -203,7 +343,8 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { - MwDrawRect(handle, rect, c); + int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; + fill_rect_rounded(handle, rect, c, MwGetInteger(handle, MwNmodernLook) ? roundness : 0); MwLLFreeColor(c); } } @@ -454,48 +595,113 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, rect->height -= border * 2; } -static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same) { - MwPoint p[7]; +#define FRAME_ARC_STEPS 6 + +/* Appends the points of an (up to) quarter-circle arc, sweeping from + * start_deg to end_deg (in degrees, either direction), to `points`. */ +static void frame_border_append_arc(MwPoint* points, int* count, int cx, int cy, int radius, double start_deg, double end_deg, int steps) { + int i; + for(i = 0; i <= steps; i++) { + double deg = start_deg + (end_deg - start_deg) * ((double)i / steps); + double rad = deg * M_PI / 180.0; + points[*count].x = cx + (int)(cos(rad) * radius); + points[*count].y = cy + (int)(sin(rad) * radius); + (*count)++; + } +} + +static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same, int roundness) { + MwPoint p[36]; + int n; + int x = rect->x; + int y = rect->y; + int w = rect->width; + int h = rect->height; + int r = roundness; + int ib, ir; (void)diff; (void)same; - p[0].x = rect->x; - p[0].y = rect->y; + if(r < 0) r = 0; + if(r > w / 2) r = w / 2; + if(r > h / 2) r = h / 2; - p[1].x = rect->x + rect->width; - p[1].y = rect->y; + if(r <= 0) { + p[0].x = x; + p[0].y = y; - p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + border; - p[3].x = rect->x + border; - p[3].y = rect->y + border; + p[1].x = x + w; + p[1].y = y; - p[4].x = rect->x + border; - p[4].y = rect->y + rect->height - border; + p[2].x = x + w - border; + p[2].y = y + border; + p[3].x = x + border; + p[3].y = y + border; - p[5].x = rect->x; - p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + p[4].x = x + border; + p[4].y = y + h - border; - p[0].x = rect->x + rect->width; - p[0].y = rect->y; + p[5].x = x; + p[5].y = y + h; + MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); - p[1].x = rect->x + rect->width - border; - p[1].y = rect->y + border; + p[0].x = x + w; + p[0].y = y; - p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + rect->height - border; + p[1].x = x + w - border; + p[1].y = y + border; - p[3].x = rect->x + border; - p[3].y = rect->y + rect->height - border; + p[2].x = x + w - border; + p[2].y = y + h - border; - p[4].x = rect->x; - p[4].y = rect->y + rect->height; + p[3].x = x + border; + p[3].y = y + h - border; - p[5].x = rect->x + rect->width; - p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + p[4].x = x; + p[4].y = y + h; + + p[5].x = x + w; + p[5].y = y + h; + MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + return; + } + + /* With rounded outer corners, each half still meets the other along + * the same two diagonals as the sharp-cornered version above, except + * the TR and BL corners (shared between both halves) are cut by an + * arc whose midpoint lies on that diagonal, and each half draws + * exactly one side of it. The TL/BR corners belong entirely to one + * half, so they get the full quarter-circle arc. + * + * The inner (border-offset) corners get the same treatment, using the + * same corner centers as the outer arcs but shrunk by the border + * width, so the border ring keeps a uniform thickness all the way + * around the curve instead of jumping to a sharp point. If the border + * is thicker than the roundness, this collapses back to the ordinary + * sharp inner corner (ib == border, ir == 0). */ + ib = (r > border) ? r : border; + ir = (r > border) ? (r - border) : 0; + + /* Top-left half: TL (full), TR (near side), BL (near side). */ + n = 0; + frame_border_append_arc(p, &n, x + r, y + r, r, 180, 270, FRAME_ARC_STEPS); + frame_border_append_arc(p, &n, x + w - r, y + r, r, 270, 315, FRAME_ARC_STEPS / 2); + frame_border_append_arc(p, &n, x + w - ib, y + ib, ir, 315, 270, FRAME_ARC_STEPS / 2); + frame_border_append_arc(p, &n, x + ib, y + ib, ir, 270, 180, FRAME_ARC_STEPS); + frame_border_append_arc(p, &n, x + ib, y + h - ib, ir, 180, 135, FRAME_ARC_STEPS / 2); + frame_border_append_arc(p, &n, x + r, y + h - r, r, 135, 180, FRAME_ARC_STEPS / 2); + MwLLPolygon(handle->lowlevel, p, n, invert ? lighter : darker); + + /* Bottom-right half: TR (far side), BL (far side), BR (full). */ + n = 0; + frame_border_append_arc(p, &n, x + w - r, y + r, r, 360, 315, FRAME_ARC_STEPS / 2); + frame_border_append_arc(p, &n, x + w - ib, y + ib, ir, 315, 360, FRAME_ARC_STEPS / 2); + frame_border_append_arc(p, &n, x + w - ib, y + h - ib, ir, 0, 90, FRAME_ARC_STEPS); + frame_border_append_arc(p, &n, x + ib, y + h - ib, ir, 90, 135, FRAME_ARC_STEPS / 2); + frame_border_append_arc(p, &n, x + r, y + h - r, r, 135, 90, FRAME_ARC_STEPS / 2); + frame_border_append_arc(p, &n, x + w - r, y + h - r, r, 90, 0, FRAME_ARC_STEPS); + MwLLPolygon(handle->lowlevel, p, n, invert ? lighter : darker); } static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { @@ -503,18 +709,19 @@ static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff); MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff); MwRect r = *rect; + int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; color_set_disabled_if_disabled(handle, darker); color_set_disabled_if_disabled(handle, lighter); - frame_border_complex(handle, rect, lighter, darker, invert, border == 1 ? 1 : (border / 2), diff, same); + frame_border_complex(handle, rect, lighter, darker, invert, border == 1 ? 1 : (border / 2), diff, same, roundness); if(border > 1) { r.x += border / 2; r.y += border / 2; r.width -= border; r.height -= border; - frame_border_complex(handle, &r, lighter, darker, !invert, border / 2, diff, same); + frame_border_complex(handle, &r, lighter, darker, !invert, border / 2, diff, same, roundness); } MwLLFreeColor(lighter); From fe17eefb215a8d2fb26b6b0599b25619a638a349 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 18:07:34 -0700 Subject: [PATCH 046/168] revert hyprland code --- src/backend/wayland/interfaces.c | 8 +- src/draw.c | 355 +++++++------------------------ 2 files changed, 76 insertions(+), 287 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index a724591..84ed492 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -40,19 +40,15 @@ static void new_protocol(void* data, struct wl_registry* registry, MwLL self = data; (void)version; (void)registry; - wayland_protocol_callback_table_t* cb; WAYLAND_EVENT_OP_START(self); - cb = shget(self->wayland.wl_protocol_setup_map, interface); + wayland_protocol_callback_table_t* cb = shget(self->wayland.wl_protocol_setup_map, interface); if(cb != NULL) { shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data, version)); - } else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) { /* we don't care for adding this protocol, we just use it to know if the compositor will let us have transparent surfaces */ + } else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) { self->common.supports_transparency = MwTRUE; - } else if(strstr(interface, "hyprland") != NULL) { - /* we have nothing to make use of with hyprland, we just want to check if we're running under it. */ - self->wayland.on_hyprland = MwTRUE; } else { // printf("unknown interface %s\n", interface); } diff --git a/src/draw.c b/src/draw.c index 19b4081..c7869e0 100644 --- a/src/draw.c +++ b/src/draw.c @@ -53,105 +53,6 @@ static void color_set_disabled_if_disabled(MwWidget handle, MwLLColor rgb) { } }; -/* Whether (x, y) within a w*h rect falls inside a rounded-rect mask of the - * given corner radius. Shared by every raster-based rounded fill below so - * they all cut the same corner shape. */ -static int rounded_rect_contains(int x, int y, int w, int h, int rad) { - int cx = -1; - int cy = -1; - - if(x < rad && y < rad) { - cx = rad; - cy = rad; - } else if(x >= w - rad && y < rad) { - cx = w - rad - 1; - cy = rad; - } else if(x < rad && y >= h - rad) { - cx = rad; - cy = h - rad - 1; - } else if(x >= w - rad && y >= h - rad) { - cx = w - rad - 1; - cy = h - rad - 1; - } - - if(cx < 0) { - return 1; - } - - { - int dx = x - cx; - int dy = y - cy; - return (dx * dx + dy * dy) <= rad * rad; - } -} - -static void fill_rect(MwWidget handle, MwRect* rect, MwLLColor color) { - MwPoint p[4]; - - p[0].x = rect->x; - p[0].y = rect->y; - - p[1].x = rect->x + rect->width; - p[1].y = rect->y; - - p[2].x = rect->x + rect->width; - p[2].y = rect->y + rect->height; - - p[3].x = rect->x; - p[3].y = rect->y + rect->height; - - MwLLPolygon(handle->lowlevel, p, 4, color); -} - -/* Flat-colored rounded-rect fill, for backdrops that need to match a rounded - * border/fill's shape instead of a plain MwDrawRect square. */ -static void fill_rect_rounded(MwWidget handle, MwRect* rect, MwLLColor color, int roundness) { - MwLLPixmap pixmap; - int x, y; - int w = rect->width; - int h = rect->height; - int rad = roundness; - unsigned char* data; - - if(w <= 0 || h <= 0) { - return; - } - - if(rad > w / 2) rad = w / 2; - if(rad > h / 2) rad = h / 2; - - if(rad <= 0) { - fill_rect(handle, rect, color); - return; - } - - data = malloc((unsigned long)w * h * 4); - if(!data) { - return; - } - - memset(data, 0, (unsigned long)w * h * 4); - - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(rounded_rect_contains(x, y, w, h, rad)) { - unsigned char* pout = &data[(y * w + x) * 4]; - - pout[0] = (unsigned char)color->common.red; - pout[1] = (unsigned char)color->common.green; - pout[2] = (unsigned char)color->common.blue; - pout[3] = 255; - } - } - } - - pixmap = MwLLCreatePixmap(handle->lowlevel, data, w, h); - MwLLDrawPixmap(handle->lowlevel, rect, pixmap); - MwLLDestroyPixmap(pixmap); - - free(data); -} - void MwParseColorNoAllocate(const char* text, MwRGB* rgb) { if(text[0] == '#' && strlen(text) == 4) { rgb->red = hex(text + 1, 1); @@ -199,104 +100,63 @@ MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b) } void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { - if(MwLLWaylandDoRoundness(handle->lowlevel)) { - fill_rect_rounded(handle, rect, color, MwLLWaylandHyprlandGetRoundness()); - } else { - fill_rect(handle, rect, color); - } + MwPoint p[4]; + + p[0].x = rect->x; + p[0].y = rect->y; + + p[1].x = rect->x + rect->width; + p[1].y = rect->y; + + p[2].x = rect->x + rect->width; + p[2].y = rect->y + rect->height; + + p[3].x = rect->x; + p[3].y = rect->y + rect->height; + + MwLLPolygon(handle->lowlevel, p, 4, color); } void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { - MwLLPixmap pixmap; - int y; - double darken = 0.; - int ColorDiff = get_color_diff(handle); - MwRect r = *rect; - int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; - - if(rect->width <= 0 || rect->height <= 0) { + MwLLPixmap pixmap; + int y; + double darken = 0.; + int ColorDiff = get_color_diff(handle); + double darkenStep = (ColorDiff / 2.) / rect->height; + unsigned long sz = 1 * rect->height * 4; + unsigned char* data = malloc(sz * 2); + MwRect r = *rect; + if(!data) { return; } + if(rect->width <= 0 || rect->height <= 0) { + free(data); + return; + } + memset(data, 0, sz); r.x += 1; r.y += 1; r.width -= 2; r.height -= 2; - if(r.width <= 0 || r.height <= 0) { - return; + for(y = 0; y < rect->height; y++) { + MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); + int idx = y * 4; + color_set_disabled_if_disabled(handle, col); + data[idx] = col->common.red; + data[idx + 1] = col->common.green; + data[idx + 2] = col->common.blue; + data[idx + 3] = 255; + MwLLFreeColor(col); + darken += darkenStep; } - if(roundness <= 0) { - double darkenStep = (ColorDiff / 2.) / rect->height; - unsigned long sz = 1 * rect->height * 4; - unsigned char* data = malloc(sz * 2); - if(!data) { - return; - } - memset(data, 0, sz); + pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + MwLLDestroyPixmap(pixmap); - for(y = 0; y < rect->height; y++) { - MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); - int idx = y * 4; - color_set_disabled_if_disabled(handle, col); - data[idx] = col->common.red; - data[idx + 1] = col->common.green; - data[idx + 2] = col->common.blue; - data[idx + 3] = 255; - MwLLFreeColor(col); - darken += darkenStep; - } - - pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); - MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - MwLLDestroyPixmap(pixmap); - - free(data); - return; - } else { - int w = r.width; - int h = r.height; - int rad = roundness; - int x; - double darkenStep; - unsigned char* data; - - if(rad > w / 2) rad = w / 2; - if(rad > h / 2) rad = h / 2; - - darkenStep = (ColorDiff / 2.) / h; - data = malloc((unsigned long)w * h * 4); - if(!data) { - return; - } - memset(data, 0, (unsigned long)w * h * 4); - - for(y = 0; y < h; y++) { - MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); - color_set_disabled_if_disabled(handle, col); - - for(x = 0; x < w; x++) { - if(rounded_rect_contains(x, y, w, h, rad)) { - unsigned char* pout = &data[(y * w + x) * 4]; - - pout[0] = (unsigned char)col->common.red; - pout[1] = (unsigned char)col->common.green; - pout[2] = (unsigned char)col->common.blue; - pout[3] = 255; - } - } - - MwLLFreeColor(col); - darken += darkenStep; - } - - pixmap = MwLLCreatePixmap(handle->lowlevel, data, w, h); - MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - MwLLDestroyPixmap(pixmap); - - free(data); - } + free(data); } void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { @@ -343,8 +203,7 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { - int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; - fill_rect_rounded(handle, rect, c, MwGetInteger(handle, MwNmodernLook) ? roundness : 0); + MwDrawRect(handle, rect, c); MwLLFreeColor(c); } } @@ -595,113 +454,48 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, rect->height -= border * 2; } -#define FRAME_ARC_STEPS 6 - -/* Appends the points of an (up to) quarter-circle arc, sweeping from - * start_deg to end_deg (in degrees, either direction), to `points`. */ -static void frame_border_append_arc(MwPoint* points, int* count, int cx, int cy, int radius, double start_deg, double end_deg, int steps) { - int i; - for(i = 0; i <= steps; i++) { - double deg = start_deg + (end_deg - start_deg) * ((double)i / steps); - double rad = deg * M_PI / 180.0; - points[*count].x = cx + (int)(cos(rad) * radius); - points[*count].y = cy + (int)(sin(rad) * radius); - (*count)++; - } -} - -static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same, int roundness) { - MwPoint p[36]; - int n; - int x = rect->x; - int y = rect->y; - int w = rect->width; - int h = rect->height; - int r = roundness; - int ib, ir; +static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same) { + MwPoint p[7]; (void)diff; (void)same; - if(r < 0) r = 0; - if(r > w / 2) r = w / 2; - if(r > h / 2) r = h / 2; + p[0].x = rect->x; + p[0].y = rect->y; - if(r <= 0) { - p[0].x = x; - p[0].y = y; + p[1].x = rect->x + rect->width; + p[1].y = rect->y; - p[1].x = x + w; - p[1].y = y; + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + border; + p[3].x = rect->x + border; + p[3].y = rect->y + border; - p[2].x = x + w - border; - p[2].y = y + border; - p[3].x = x + border; - p[3].y = y + border; + p[4].x = rect->x + border; + p[4].y = rect->y + rect->height - border; - p[4].x = x + border; - p[4].y = y + h - border; + p[5].x = rect->x; + p[5].y = rect->y + rect->height; + MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); - p[5].x = x; - p[5].y = y + h; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + p[0].x = rect->x + rect->width; + p[0].y = rect->y; - p[0].x = x + w; - p[0].y = y; + p[1].x = rect->x + rect->width - border; + p[1].y = rect->y + border; - p[1].x = x + w - border; - p[1].y = y + border; + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + rect->height - border; - p[2].x = x + w - border; - p[2].y = y + h - border; + p[3].x = rect->x + border; + p[3].y = rect->y + rect->height - border; - p[3].x = x + border; - p[3].y = y + h - border; + p[4].x = rect->x; + p[4].y = rect->y + rect->height; - p[4].x = x; - p[4].y = y + h; - - p[5].x = x + w; - p[5].y = y + h; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); - return; - } - - /* With rounded outer corners, each half still meets the other along - * the same two diagonals as the sharp-cornered version above, except - * the TR and BL corners (shared between both halves) are cut by an - * arc whose midpoint lies on that diagonal, and each half draws - * exactly one side of it. The TL/BR corners belong entirely to one - * half, so they get the full quarter-circle arc. - * - * The inner (border-offset) corners get the same treatment, using the - * same corner centers as the outer arcs but shrunk by the border - * width, so the border ring keeps a uniform thickness all the way - * around the curve instead of jumping to a sharp point. If the border - * is thicker than the roundness, this collapses back to the ordinary - * sharp inner corner (ib == border, ir == 0). */ - ib = (r > border) ? r : border; - ir = (r > border) ? (r - border) : 0; - - /* Top-left half: TL (full), TR (near side), BL (near side). */ - n = 0; - frame_border_append_arc(p, &n, x + r, y + r, r, 180, 270, FRAME_ARC_STEPS); - frame_border_append_arc(p, &n, x + w - r, y + r, r, 270, 315, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + w - ib, y + ib, ir, 315, 270, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + ib, y + ib, ir, 270, 180, FRAME_ARC_STEPS); - frame_border_append_arc(p, &n, x + ib, y + h - ib, ir, 180, 135, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + r, y + h - r, r, 135, 180, FRAME_ARC_STEPS / 2); - MwLLPolygon(handle->lowlevel, p, n, invert ? lighter : darker); - - /* Bottom-right half: TR (far side), BL (far side), BR (full). */ - n = 0; - frame_border_append_arc(p, &n, x + w - r, y + r, r, 360, 315, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + w - ib, y + ib, ir, 315, 360, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + w - ib, y + h - ib, ir, 0, 90, FRAME_ARC_STEPS); - frame_border_append_arc(p, &n, x + ib, y + h - ib, ir, 90, 135, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + r, y + h - r, r, 135, 90, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + w - r, y + h - r, r, 90, 0, FRAME_ARC_STEPS); - MwLLPolygon(handle->lowlevel, p, n, invert ? lighter : darker); + p[5].x = rect->x + rect->width; + p[5].y = rect->y + rect->height; + MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); } static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { @@ -709,19 +503,18 @@ static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff); MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff); MwRect r = *rect; - int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; color_set_disabled_if_disabled(handle, darker); color_set_disabled_if_disabled(handle, lighter); - frame_border_complex(handle, rect, lighter, darker, invert, border == 1 ? 1 : (border / 2), diff, same, roundness); + frame_border_complex(handle, rect, lighter, darker, invert, border == 1 ? 1 : (border / 2), diff, same); if(border > 1) { r.x += border / 2; r.y += border / 2; r.width -= border; r.height -= border; - frame_border_complex(handle, &r, lighter, darker, !invert, border / 2, diff, same, roundness); + frame_border_complex(handle, &r, lighter, darker, !invert, border / 2, diff, same); } MwLLFreeColor(lighter); From 18d397b4f82121383bd1dd5c9d7c9f7fbc25020a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 19:22:32 -0700 Subject: [PATCH 047/168] wh --- CMakeLists.txt | 1 - include/Mw/LowLevel/Wayland.h | 12 +-- pl/rules.pl | 1 - src/backend/cairo.c | 12 +-- src/backend/wayland/hyprland.c | 60 ----------- src/backend/wayland/interfaces.c | 153 +++++++++++++++++---------- src/backend/wayland/wayland.c | 176 ++++++++++++++++--------------- 7 files changed, 200 insertions(+), 215 deletions(-) delete mode 100644 src/backend/wayland/hyprland.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d072daf..534614f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,7 +269,6 @@ if(MW_USE_WAYLAND) src/backend/cairo.c src/backend/wayland/wayland.c src/backend/wayland/buffer.c - src/backend/wayland/hyprland.c src/backend/wayland/interfaces.c src/backend/wayland/region.c ) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 0f570e3..c42231c 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -238,8 +238,6 @@ struct _MwLLWaylandTopLevel { }; struct _MwLLWaylandSublevel { - struct wl_subsurface* subsurface; - struct wl_subcompositor* subcompositor; MwLL parent; @@ -488,8 +486,9 @@ int MwLLWaylandHyprlandGetRoundness(void); void MwLLWaylandHangUntilConfigured(MwLL handle); -MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); -void MwLLWaylandWidgetUndestroy(MwLL self); +// MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); +// void MwLLWaylandWidgetUndestroy(MwLL self); +void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)); /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland); @@ -500,10 +499,7 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_ void MwLLWaylandFlush(MwLL handle); /* Standard procedure before event callbacks in Wayland */ -#define WAYLAND_EVENT_OP_START(self) \ - if(MwLLWaylandWidgetIsDestroyed(self)) { \ - return; \ - } +#define WAYLAND_EVENT_OP_START(self) /* Footer for WAYLAND_EVENT_OP_START */ #define WAYLAND_EVENT_OP_END(self) diff --git a/pl/rules.pl b/pl/rules.pl index 80f930d..986ee98 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -49,7 +49,6 @@ if (grep(/^wayland$/, @backends)) { new_object("src/backend/cairo.c"); new_object("src/backend/wayland/wayland.c"); new_object("src/backend/wayland/buffer.c"); - new_object("src/backend/wayland/hyprland.c"); new_object("src/backend/wayland/interfaces.c"); new_object("src/backend/wayland/region.c"); diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 65380fb..d70de1b 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -212,8 +212,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -257,10 +257,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/wayland/hyprland.c b/src/backend/wayland/hyprland.c deleted file mode 100644 index e6c8679..0000000 --- a/src/backend/wayland/hyprland.c +++ /dev/null @@ -1,60 +0,0 @@ -#include - -int MwLLWaylandDoRoundness(MwLL handle) { - if(handle->common.type == MwLLBackendWayland) { - return handle->wayland.on_hyprland; - } else { - return 0; - }; -}; - -int MwLLWaylandHyprlandGetRoundness(void) { - char* home = getenv("HOME"); - int fallback = 20; - char path[PATH_MAX]; - int roundness = fallback; - char line[512]; - FILE* f = NULL; - - if(home == NULL) { - return fallback; - } - - snprintf(path, sizeof(path), "%s/.config/hypr/hyprland.lua", home); - - f = fopen(path, "r"); - if(f == NULL) { - return fallback; - } - - while(fgets(line, sizeof(line), f) != NULL) { - char* key = strstr(line, "roundness"); - char* eq; - char* end; - long value; - - if(key == NULL) { - continue; - } - - eq = strchr(key, '='); - if(eq == NULL) { - continue; - } - eq++; - - while(*eq != '\0' && isspace((unsigned char)*eq)) { - eq++; - } - - value = strtol(eq, &end, 10); - if(end == eq) { - continue; - } - - roundness = (int)value; - } - - fclose(f); - return roundness; -} diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 84ed492..caf62ac 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -531,8 +531,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time MwLL self = data; MwLL topmost_parent = self; MwMouse p; - MwBool inArea = MwFALSE; - MwLL currentlyHeldWidget = NULL; + MwBool inArea = MwFALSE; (void)time; (void)wl_pointer; @@ -540,8 +539,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time WAYLAND_EVENT_OP_START(self); while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - currentlyHeldWidget = topmost_parent->wayland.currentlyHeldWidget; - if(self->wayland.framebuffer.surface) { inArea |= self->wayland.framebuffer.surface == curSurface; } @@ -552,30 +549,92 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); - if(currentlyHeldWidget != NULL) { - currentlyHeldWidget->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); - currentlyHeldWidget->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); - } if(inArea) { p.point = self->wayland.cur_mouse_pos; MwLLDispatch(self, move, &p); - wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); - } else if(currentlyHeldWidget == self) { - p.point = currentlyHeldWidget->wayland.cur_mouse_pos; - MwLLDispatch(currentlyHeldWidget, move, &p); } WAYLAND_EVENT_OP_END(self); }; +// static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { +// MwWidget h = (MwWidget)handle->common.user; +// MwLLDispatch(handle, down, p); +// if(h) { +// int i; +// for(i = 0; i < arrlen(h->children); i++) { +// MwLLDispatch(h->children[i]->lowlevel, down, p); +// if(arrlen(h->children[i]->children) > 0) { +// recursive_dispatch_mouse_down(h->children[i]->lowlevel, p); +// } +// } +// } +// }; +// static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { +// MwWidget h = (MwWidget)handle->common.user; +// MwLLDispatch(handle, up, p); +// if(h) { +// int i; +// for(i = 0; i < arrlen(h->children); i++) { +// MwLLDispatch(h->children[i]->lowlevel, up, p); +// if(arrlen(h->children[i]->children) > 0) { +// recursive_dispatch_mouse_up(h->children[i]->lowlevel, p); +// } +// } +// } +// }; + +static void pointer_iterate_master(MwLL handle, MwLL child, MwBool down) { + MwLL topmost_parent = handle; + MwPoint point; + MwPoint relative_pos; + MwPoint absolute_pos; + + absolute_pos.x = child->wayland.x; + absolute_pos.y = child->wayland.y; + + while(topmost_parent->wayland.parent) { + topmost_parent = topmost_parent->wayland.parent; + if(topmost_parent) { + absolute_pos.x += topmost_parent->wayland.x; + absolute_pos.y += topmost_parent->wayland.y; + } + } + + point = topmost_parent->wayland.cur_mouse_pos; + relative_pos.x = point.x - absolute_pos.x; + relative_pos.y = point.y - absolute_pos.y; + + if( + point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && + point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh) { + MwMouse p; + p.point = relative_pos; + + if(down) { + MwLLDispatch(child, down, &p); + } else { + MwLLDispatch(child, up, &p); + } + + printf("%p %s (%d %d %d %d)\n", child, down ? "DOWN" : "UP", p.point.x, p.point.y, child->wayland.ww, child->wayland.wh); + } +} +static void pointer_iterate_down(MwLL handle, MwLL child) { + pointer_iterate_master(handle, child, MwTRUE); + MwLLWaylandChildrenIterate(child, pointer_iterate_down); +} +static void pointer_iterate_up(MwLL handle, MwLL child) { + pointer_iterate_master(handle, child, MwFALSE); + MwLLWaylandChildrenIterate(child, pointer_iterate_up); +} + /* `wl_pointer.button` callback */ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) { MwLL self = data; MwMouse p; - MwBool inArea = MwFALSE; - MwLL topmost_parent = self; (void)wl_pointer; (void)serial; @@ -584,46 +643,29 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri WAYLAND_EVENT_OP_START(self); p.point = self->wayland.cur_mouse_pos; - while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - if(self->wayland.framebuffer.surface) { - inArea |= self->wayland.framebuffer.surface == curSurface; + switch(button) { + case BTN_LEFT: + p.button = MwMOUSE_LEFT; + break; + case BTN_MIDDLE: + p.button = MwMOUSE_MIDDLE; + break; + case BTN_RIGHT: + p.button = MwMOUSE_RIGHT; + break; } - if(self->wayland.backbuffer.surface) { - inArea |= self->wayland.backbuffer.surface == curSurface; - } - if(inArea) { - switch(button) { - case BTN_LEFT: - p.button = MwMOUSE_LEFT; - break; - case BTN_MIDDLE: - p.button = MwMOUSE_MIDDLE; - break; - case BTN_RIGHT: - p.button = MwMOUSE_RIGHT; - break; - } - self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; + self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; - switch(state) { - case WL_POINTER_BUTTON_STATE_PRESSED: - if(button == BTN_LEFT) { - topmost_parent->wayland.focusedWidget = self; - } - MwLLDispatch(self, down, &p); - topmost_parent->wayland.currentlyHeldWidget = self; - - break; - case WL_POINTER_BUTTON_STATE_RELEASED: - if(topmost_parent->wayland.currentlyHeldWidget != NULL) { - MwLLDispatch(topmost_parent->wayland.currentlyHeldWidget, up, &p); - topmost_parent->wayland.currentlyHeldWidget = NULL; - } else { - MwLLDispatch(self, up, &p); - } - break; - } + switch(state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + MwLLDispatch(self, down, &p); + MwLLWaylandChildrenIterate(self, pointer_iterate_down); + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + MwLLDispatch(self, up, &p); + MwLLWaylandChildrenIterate(self, pointer_iterate_up); + break; } if(!self->wayland.has_decorations && self->wayland.do_csd) { @@ -1056,7 +1098,7 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } else { - wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + // wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } return NULL; @@ -1067,7 +1109,7 @@ static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, way if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wl_subcompositor_destroy(wayland->toplevel->scompositor); } else { - wl_subcompositor_destroy(wayland->sublevel->subcompositor); + // wl_subcompositor_destroy(wayland->sublevel->subcompositor); } } @@ -1201,7 +1243,6 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(wl_shm); WL_INTERFACE(wl_compositor); - WL_INTERFACE(wl_seat); WL_INTERFACE(wl_output); WL_INTERFACE(wl_data_device_manager); WL_INTERFACE(zwp_primary_selection_device_manager_v1); @@ -1214,10 +1255,14 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); WL_INTERFACE(wl_subcompositor); + WL_INTERFACE(wl_seat); } else if(wayland->type == MwLL_WAYLAND_POPUP) { + WL_INTERFACE(wl_seat); } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { WL_INTERFACE(wp_viewporter); WL_INTERFACE(wl_subcompositor); + WL_INTERFACE(wl_seat); + WL_INTERFACE(wl_seat); } else { WL_INTERFACE(wl_subcompositor); } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 82c053e..22c5137 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -12,37 +12,51 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; -static pthread_mutex_t destroyedWidgetsTableMutex; -/* - * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. - * - * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. - */ -static MwLL* destroyedWidgetsTable; +// static pthread_mutex_t destroyedWidgetsTableMutex; +// /* +// * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. +// * +// * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. +// */ +// static MwLL* destroyedWidgetsTable; -MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { - int i; - pthread_mutex_lock(&destroyedWidgetsTableMutex); - for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { - if(self == destroyedWidgetsTable[i]) { - pthread_mutex_unlock(&destroyedWidgetsTableMutex); - return MwTRUE; +// MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { +// int i; +// pthread_mutex_lock(&destroyedWidgetsTableMutex); +// for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { +// if(self == destroyedWidgetsTable[i]) { +// pthread_mutex_unlock(&destroyedWidgetsTableMutex); +// return MwTRUE; +// } +// } +// pthread_mutex_unlock(&destroyedWidgetsTableMutex); +// return MwFALSE; +// } +// void MwLLWaylandWidgetUndestroy(MwLL self) { +// int i; +// pthread_mutex_lock(&destroyedWidgetsTableMutex); +// for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { +// if(self == destroyedWidgetsTable[i]) { +// arrdel(destroyedWidgetsTable, i); +// break; +// } +// } +// pthread_mutex_unlock(&destroyedWidgetsTableMutex); +// return; +// } +// + +void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { + if(handle->common.user) { + MwWidget w = handle->common.user; + int i; + for(i = 0; i < arrlen(w->children); i++) { + if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { + MwLL child = w->children[i]->lowlevel; + func(handle, child); + } } } - pthread_mutex_unlock(&destroyedWidgetsTableMutex); - return MwFALSE; -} -void MwLLWaylandWidgetUndestroy(MwLL self) { - int i; - pthread_mutex_lock(&destroyedWidgetsTableMutex); - for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { - if(self == destroyedWidgetsTable[i]) { - arrdel(destroyedWidgetsTable, i); - break; - } - } - pthread_mutex_unlock(&destroyedWidgetsTableMutex); - return; } static int event_loop(MwLL handle); @@ -370,18 +384,6 @@ static void destroy_toplevel(MwLL r) { wl_pointer_destroy(r->wayland.pointer); wl_keyboard_destroy(r->wayland.keyboard); - if(r->common.user) { - MwWidget w = r->common.user; - int i; - for(i = 0; i < arrlen(w->children); i++) { - if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - MwLL child = w->children[i]->lowlevel; - wl_subsurface_destroy(child->wayland.sublevel->subsurface); - child->wayland.sublevel->subsurface = NULL; - } - } - } - wl_surface_destroy(r->wayland.framebuffer.surface); free(r->wayland.toplevel); @@ -421,22 +423,12 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor); - r->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(r->wayland.sublevel->subcompositor, r->wayland.framebuffer.surface, parent_surface); - - wl_subsurface_set_desync(r->wayland.sublevel->subsurface); - wl_subsurface_set_position(r->wayland.sublevel->subsurface, x, y); - - if(parent) { - wl_subsurface_place_above(r->wayland.sublevel->subsurface, parent->wayland.framebuffer.surface); - } - r->wayland.xkb_keymap = parent->wayland.xkb_keymap; r->wayland.xkb_state = parent->wayland.xkb_state; r->wayland.configured = MwTRUE; MwLLWaylandFramebufferSetup(&r->wayland); - MwLLWaylandBackbufferSetup(&r->wayland); } /* Sublevel setup function */ @@ -444,8 +436,6 @@ static void destroy_sublevel(MwLL r) { MwLLWaylandBackbufferDestroy(&r->wayland); MwLLWaylandFramebufferDestroy(&r->wayland); - wl_subsurface_destroy(r->wayland.sublevel->subsurface); - free(r->wayland.sublevel); r->wayland.configured = MwFALSE; @@ -873,12 +863,7 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.x = x; r->wayland.y = y; r->wayland.parent = parent; - if(MwLLWaylandWidgetIsDestroyed(parent)) { - r->wayland.valid = MwFALSE; - return; - } else { - r->wayland.valid = MwTRUE; - } + r->wayland.valid = MwTRUE; if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { @@ -963,10 +948,6 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { memset(r, 0, sizeof(*r)); MwLLCreateCommon(r); - if(MwLLWaylandWidgetIsDestroyed(r)) { - MwLLWaylandWidgetUndestroy(r); - } - r->wayland.is_toplevel = parent == NULL; r->wayland.is_clipping = 0; @@ -1030,15 +1011,11 @@ static void MwLLDestroyImpl(MwLL handle) { printf("widget invalid\n"); } - pthread_mutex_lock(&destroyedWidgetsTableMutex); - arrput(destroyedWidgetsTable, handle); - pthread_mutex_unlock(&destroyedWidgetsTableMutex); + // pthread_mutex_lock(&destroyedWidgetsTableMutex); + // arrput(destroyedWidgetsTable, handle); + // pthread_mutex_unlock(&destroyedWidgetsTableMutex); free(handle); - - // if(topmost_parent->wayland.currentlyHeldWidget == handle) { - // topmost_parent->wayland.currentlyHeldWidget = NULL; - // } } static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { @@ -1066,7 +1043,7 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { /* toplevels cannot be moved */ break; case MwLL_WAYLAND_SUBLEVEL: - wl_subsurface_set_position(handle->wayland.sublevel->subsurface, x, y); + /* sublevels are drawn according to their own x/y */ break; case MwLL_WAYLAND_POPUP: xdg_positioner_set_anchor_rect(handle->wayland.popup->xdg_positioner, handle->wayland.parent->wayland.x, handle->wayland.parent->wayland.y, handle->wayland.ww, handle->wayland.wh); @@ -1142,6 +1119,41 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { handle->wayland.events_pending = 1; } +static void draw_child(MwLL handle, MwLL child); +static void draw_children(MwLL handle); + +static void draw_child(MwLL handle, MwLL child) { + cairo_t* c; + cairo_surface_t* cs; + cairo_t* selected_cairo = handle->wayland.cairo.front_cairo; + + wl_surface_commit(child->wayland.framebuffer.surface); + + cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, child->wayland.ww, child->wayland.wh); + c = cairo_create(cs); + + cairo_set_source_surface(c, child->wayland.cairo.front_cs, 0, 0); + cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); + + cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_OVER); + + cairo_paint(c); + + cairo_set_source_surface(selected_cairo, cs, child->wayland.x, child->wayland.y); + cairo_paint(selected_cairo); + + cairo_destroy(c); + cairo_surface_destroy(cs); + + draw_children(child); +} + +static void draw_children(MwLL handle) { + MwLLWaylandChildrenIterate(handle, draw_child); + + wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + handle->wayland.force_render = MwTRUE; +} typedef struct { double r, g, b; @@ -1304,6 +1316,8 @@ static void MwLLEndDrawImpl(MwLL handle) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); + + draw_children(handle); } } @@ -1361,10 +1375,6 @@ static int MwLLPendingImpl(MwLL handle) { }; int pending = 0; - if(MwLLWaylandWidgetIsDestroyed(handle) || !handle->wayland.valid) { - return 0; - } - handle->wayland.resizing = 0; if(handle->wayland.setting_wh) { @@ -1670,7 +1680,7 @@ static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { dec->decoration, toggle ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); } else { handle->wayland.do_csd = !toggle; - wl_subsurface_set_position(handle->wayland.toplevel->ssurface, handle->wayland.do_csd ? CSD_BORDER_FRAME_LEFT : 0, handle->wayland.do_csd ? CSD_BORDER_FRAME_TOP : 0); + // wl_subsurface_set_position(handle->wayland.toplevel->ssurface, handle->wayland.do_csd ? CSD_BORDER_FRAME_LEFT : 0, handle->wayland.do_csd ? CSD_BORDER_FRAME_TOP : 0); } } } @@ -1845,20 +1855,16 @@ static void MwLLEndStateChangeImpl(MwLL handle) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { MwLL child = w->children[i]->lowlevel; child->wayland.sublevel->xdg_surface = handle->wayland.popup->xdg_surface; - if(child->wayland.sublevel->subsurface) - wl_subsurface_destroy(child->wayland.sublevel->subsurface); + // if(child->wayland.sublevel->subsurface) + // wl_subsurface_destroy(child->wayland.sublevel->subsurface); MwLLWaylandFlush(handle); - child->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(child->wayland.sublevel->subcompositor, child->wayland.framebuffer.surface, handle->wayland.framebuffer.surface); - wl_subsurface_set_desync(child->wayland.sublevel->subsurface); - wl_subsurface_set_position(child->wayland.sublevel->subsurface, child->wayland.x, child->wayland.y); + // child->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(child->wayland.sublevel->subcompositor, child->wayland.framebuffer.surface, handle->wayland.framebuffer.surface); + // wl_subsurface_set_desync(child->wayland.sublevel->subsurface); + // wl_subsurface_set_position(child->wayland.sublevel->subsurface, child->wayland.x, child->wayland.y); - wl_subsurface_place_above(child->wayland.sublevel->subsurface, handle->wayland.framebuffer.surface); + // wl_subsurface_place_above(child->wayland.sublevel->subsurface, handle->wayland.framebuffer.surface); MwLLEndStateChangeImpl(w->children[i]->lowlevel); - - if(topmost_parent) { - topmost_parent->wayland.currentlyHeldWidget = NULL; - } } } } From f25b67652343b83dadf0b7c2a34e70d3caa20126 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 21:00:38 -0700 Subject: [PATCH 048/168] and now to merge --- include/Mw/LowLevel/Wayland.h | 4 +- src/backend/wayland/interfaces.c | 141 ++++++++++++++++--------------- src/backend/wayland/wayland.c | 105 ++++++++++++++--------- 3 files changed, 141 insertions(+), 109 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c42231c..0bfe201 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -424,6 +424,8 @@ struct _MwLLWayland { MwBool force_render; MwBool did_event_loop_early; + MwBool do_cascading_draw; + int cascading_child_num; MwBool dispatching_resize; @@ -452,8 +454,6 @@ struct _MwLLWayland { MwU64 next_elapsed; long start_time; long end_time; - - MwBool on_hyprland; }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index caf62ac..43703a9 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -559,76 +559,79 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time WAYLAND_EVENT_OP_END(self); }; -// static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { -// MwWidget h = (MwWidget)handle->common.user; -// MwLLDispatch(handle, down, p); -// if(h) { -// int i; -// for(i = 0; i < arrlen(h->children); i++) { -// MwLLDispatch(h->children[i]->lowlevel, down, p); -// if(arrlen(h->children[i]->children) > 0) { -// recursive_dispatch_mouse_down(h->children[i]->lowlevel, p); -// } -// } -// } -// }; -// static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { -// MwWidget h = (MwWidget)handle->common.user; -// MwLLDispatch(handle, up, p); -// if(h) { -// int i; -// for(i = 0; i < arrlen(h->children); i++) { -// MwLLDispatch(h->children[i]->lowlevel, up, p); -// if(arrlen(h->children[i]->children) > 0) { -// recursive_dispatch_mouse_up(h->children[i]->lowlevel, p); -// } -// } -// } -// }; - -static void pointer_iterate_master(MwLL handle, MwLL child, MwBool down) { - MwLL topmost_parent = handle; - MwPoint point; - MwPoint relative_pos; - MwPoint absolute_pos; - - absolute_pos.x = child->wayland.x; - absolute_pos.y = child->wayland.y; - - while(topmost_parent->wayland.parent) { - topmost_parent = topmost_parent->wayland.parent; - if(topmost_parent) { - absolute_pos.x += topmost_parent->wayland.x; - absolute_pos.y += topmost_parent->wayland.y; +static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { + MwWidget h = (MwWidget)handle->common.user; + MwLLDispatch(handle, down, p); + if(h) { + int i; + for(i = 0; i < arrlen(h->children); i++) { + MwLLDispatch(h->children[i]->lowlevel, down, p); + if(arrlen(h->children[i]->children) > 0) { + recursive_dispatch_mouse_down(h->children[i]->lowlevel, p); + } } } - - point = topmost_parent->wayland.cur_mouse_pos; - relative_pos.x = point.x - absolute_pos.x; - relative_pos.y = point.y - absolute_pos.y; - - if( - point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && - point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh) { - MwMouse p; - p.point = relative_pos; - - if(down) { - MwLLDispatch(child, down, &p); - } else { - MwLLDispatch(child, up, &p); +}; +static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { + MwWidget h = (MwWidget)handle->common.user; + MwLLDispatch(handle, up, p); + if(h) { + int i; + for(i = 0; i < arrlen(h->children); i++) { + MwLLDispatch(h->children[i]->lowlevel, up, p); + if(arrlen(h->children[i]->children) > 0) { + recursive_dispatch_mouse_up(h->children[i]->lowlevel, p); + } + } + } +}; + +static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { + switch(state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + MwLLDispatch(self, down, &p); + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + MwLLDispatch(self, up, &p); + break; + } + + if(self->common.user) { + MwWidget w = self->common.user; + int i; + for(i = 0; i < arrlen(w->children); i++) { + if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { + MwLL child = w->children[i]->lowlevel; + MwLL topmost_parent = child; + MwPoint point; + MwPoint relative_mouse_pos; + MwPoint absolute_pos; + + absolute_pos.x = child->wayland.x; + absolute_pos.y = child->wayland.y; + while(topmost_parent->wayland.parent) { + topmost_parent = topmost_parent->wayland.parent; + if(topmost_parent) { + absolute_pos.x += topmost_parent->wayland.x; + absolute_pos.y += topmost_parent->wayland.y; + } + } + + point = topmost_parent->wayland.cur_mouse_pos; + relative_mouse_pos.x = point.x - absolute_pos.x; + relative_mouse_pos.y = point.y - absolute_pos.y; + + if( + point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && + point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh) { + + p.point = relative_mouse_pos; + + mouse_dispatch(child, p, state); + } + } } - - printf("%p %s (%d %d %d %d)\n", child, down ? "DOWN" : "UP", p.point.x, p.point.y, child->wayland.ww, child->wayland.wh); } -} -static void pointer_iterate_down(MwLL handle, MwLL child) { - pointer_iterate_master(handle, child, MwTRUE); - MwLLWaylandChildrenIterate(child, pointer_iterate_down); -} -static void pointer_iterate_up(MwLL handle, MwLL child) { - pointer_iterate_master(handle, child, MwFALSE); - MwLLWaylandChildrenIterate(child, pointer_iterate_up); } /* `wl_pointer.button` callback */ @@ -656,17 +659,15 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri break; } self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; - switch(state) { case WL_POINTER_BUTTON_STATE_PRESSED: MwLLDispatch(self, down, &p); - MwLLWaylandChildrenIterate(self, pointer_iterate_down); break; case WL_POINTER_BUTTON_STATE_RELEASED: MwLLDispatch(self, up, &p); - MwLLWaylandChildrenIterate(self, pointer_iterate_up); break; } + mouse_dispatch(self, p, state); if(!self->wayland.has_decorations && self->wayland.do_csd) { if(state != WL_POINTER_BUTTON_STATE_RELEASED) @@ -675,6 +676,8 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri xdg_borderless_step_mup(self, p, serial); } + MwLLForceRender(self); + WAYLAND_EVENT_OP_END(self); }; diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 22c5137..c8c4b01 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -942,6 +942,60 @@ static void detect_dark_theme(MwLL handle) { } #endif +static void draw_child(MwLL handle, MwLL child); +static void draw_children(MwLL handle); + +static void draw_child(MwLL handle, MwLL child) { + cairo_t* c; + cairo_surface_t* cs; + cairo_t* selected_cairo = handle->wayland.cairo.front_cairo; + + wl_surface_commit(child->wayland.framebuffer.surface); + + cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, child->wayland.ww, child->wayland.wh); + c = cairo_create(cs); + + cairo_set_source_surface(c, child->wayland.cairo.front_cs, 0, 0); + cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); + + cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_OVER); + + cairo_paint(c); + + cairo_set_source_surface(selected_cairo, cs, child->wayland.x, child->wayland.y); + cairo_paint(selected_cairo); + + cairo_destroy(c); + cairo_surface_destroy(cs); + + draw_children(child); +} + +static void draw_children(MwLL handle) { + wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + + MwLLWaylandChildrenIterate(handle, draw_child); + + if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); + handle->wayland.events_pending = MwFALSE; +} + +static void cascade_child(MwLL handle, MwLL child) { + child->wayland.do_cascading_draw = 10; +} + +static void count_child(MwLL handle, MwLL child) { + handle->wayland.cascading_child_num++; +} + +static void cascade_children(MwLL handle) { + handle->wayland.cascading_child_num = 0; + MwLLWaylandChildrenIterate(handle, count_child); + + handle->wayland.do_cascading_draw = 10; + MwLLWaylandChildrenIterate(handle, cascade_child); +} + static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); @@ -1035,8 +1089,11 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign static void MwLLSetXYImpl(MwLL handle, int x, int y) { WIDGET_CHECK(handle); MwLLWaylandRegionInvalidate(handle); - handle->wayland.x = x; - handle->wayland.y = y; + + if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) { + handle->wayland.x = x; + handle->wayland.y = y; + } switch(handle->wayland.type) { case MwLL_WAYLAND_TOPLEVEL: @@ -1119,41 +1176,6 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { handle->wayland.events_pending = 1; } -static void draw_child(MwLL handle, MwLL child); -static void draw_children(MwLL handle); - -static void draw_child(MwLL handle, MwLL child) { - cairo_t* c; - cairo_surface_t* cs; - cairo_t* selected_cairo = handle->wayland.cairo.front_cairo; - - wl_surface_commit(child->wayland.framebuffer.surface); - - cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, child->wayland.ww, child->wayland.wh); - c = cairo_create(cs); - - cairo_set_source_surface(c, child->wayland.cairo.front_cs, 0, 0); - cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); - - cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_OVER); - - cairo_paint(c); - - cairo_set_source_surface(selected_cairo, cs, child->wayland.x, child->wayland.y); - cairo_paint(selected_cairo); - - cairo_destroy(c); - cairo_surface_destroy(cs); - - draw_children(child); -} - -static void draw_children(MwLL handle) { - MwLLWaylandChildrenIterate(handle, draw_child); - - wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - handle->wayland.force_render = MwTRUE; -} typedef struct { double r, g, b; @@ -1317,7 +1339,7 @@ static void MwLLEndDrawImpl(MwLL handle) { } MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); - draw_children(handle); + cascade_children(handle); } } @@ -1382,6 +1404,12 @@ static int MwLLPendingImpl(MwLL handle) { handle->wayland.setting_wh = 0; } + if(handle->wayland.do_cascading_draw) { + draw_children(handle); + if(handle->wayland.do_cascading_draw > 0) + handle->wayland.do_cascading_draw--; + } + handle->wayland.end_time = MwTimeGetTick(); if(handle->wayland.holding_key) { @@ -1440,6 +1468,7 @@ static int MwLLPendingImpl(MwLL handle) { static void MwLLNextEventImpl(MwLL handle) { WIDGET_CHECK(handle); + if(!MwWaylandVulkan) { if(handle->wayland.did_event_loop_early) { handle->wayland.did_event_loop_early = MwFALSE; From 5d5170e6cac8ece784b3ac366c86fe9697730620 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 21:23:20 -0700 Subject: [PATCH 049/168] currentlyHeldWidget brought back --- include/Mw/LowLevel/Wayland.h | 15 ++++++--- src/backend/wayland/interfaces.c | 48 +++++++++++++++++++++++++-- src/backend/wayland/wayland.c | 57 ++++++++++++++++---------------- 3 files changed, 83 insertions(+), 37 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 0bfe201..f7102ce 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -412,7 +412,7 @@ struct _MwLLWayland { MwI32 ox, oy; MwU32 ww, wh; /* Window position */ MwPoint cur_mouse_pos; /* Currently known mouse position */ - MwLL currentlyHeldWidget; + MwLL* currentlyHeldWidgets; MwLL focusedWidget; int resizing; @@ -486,9 +486,9 @@ int MwLLWaylandHyprlandGetRoundness(void); void MwLLWaylandHangUntilConfigured(MwLL handle); -// MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); -// void MwLLWaylandWidgetUndestroy(MwLL self); -void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)); +MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); +void MwLLWaylandWidgetUndestroy(MwLL self); +void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)); /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland); @@ -498,8 +498,13 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_ /* Flush Wayland events */ void MwLLWaylandFlush(MwLL handle); +void MwLLWaylandCascadeChildren(MwLL handle); + /* Standard procedure before event callbacks in Wayland */ -#define WAYLAND_EVENT_OP_START(self) +#define WAYLAND_EVENT_OP_START(self) \ + if(MwLLWaylandWidgetIsDestroyed(self)) { \ + return; \ + } /* Footer for WAYLAND_EVENT_OP_START */ #define WAYLAND_EVENT_OP_END(self) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 43703a9..706318a 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -531,7 +531,9 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time MwLL self = data; MwLL topmost_parent = self; MwMouse p; - MwBool inArea = MwFALSE; + MwBool inArea = MwFALSE; + MwLL* currentlyHeldWidgets = NULL; + int i; (void)time; (void)wl_pointer; @@ -539,6 +541,8 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time WAYLAND_EVENT_OP_START(self); while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; + currentlyHeldWidgets = topmost_parent->wayland.currentlyHeldWidgets; + if(self->wayland.framebuffer.surface) { inArea |= self->wayland.framebuffer.surface == curSurface; } @@ -555,6 +559,19 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time MwLLDispatch(self, move, &p); wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); } + for(i = 0; i < arrlen(currentlyHeldWidgets); i++) { + MwLL new_topmost = currentlyHeldWidgets[i]; + p.point = topmost_parent->wayland.cur_mouse_pos; + while(new_topmost->wayland.parent) { + p.point.x -= new_topmost->wayland.x; + p.point.y -= new_topmost->wayland.y; + new_topmost = new_topmost->wayland.parent; + } + + MwLLDispatch(currentlyHeldWidgets[i], move, &p); + } + + MwLLWaylandCascadeChildren(self); WAYLAND_EVENT_OP_END(self); }; @@ -598,7 +615,7 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { if(self->common.user) { MwWidget w = self->common.user; - int i; + int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { MwLL child = w->children[i]->lowlevel; @@ -624,9 +641,27 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { if( point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh) { - + int idx = -1; + for(n = 0; n < arrlen(topmost_parent->wayland.currentlyHeldWidgets); n++) { + if(topmost_parent->wayland.currentlyHeldWidgets[n] == child) { + idx = n; + } + } p.point = relative_mouse_pos; + switch(state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + if(idx == -1) { + arrpush(topmost_parent->wayland.currentlyHeldWidgets, child); + } + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + if(idx != -1) { + arrdel(topmost_parent->wayland.currentlyHeldWidgets, idx); + } + break; + } + mouse_dispatch(child, p, state); } } @@ -638,12 +673,15 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) { MwLL self = data; MwMouse p; + MwLL topmost_parent = self; + int i; (void)wl_pointer; (void)serial; (void)time; WAYLAND_EVENT_OP_START(self); + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; p.point = self->wayland.cur_mouse_pos; @@ -667,6 +705,10 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri MwLLDispatch(self, up, &p); break; } + + for(i = 0; i < arrlen(self->wayland.currentlyHeldWidgets); i++) { + arrdel(self->wayland.currentlyHeldWidgets, i); + } mouse_dispatch(self, p, state); if(!self->wayland.has_decorations && self->wayland.do_csd) { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index c8c4b01..d032e7d 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -12,39 +12,38 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; -// static pthread_mutex_t destroyedWidgetsTableMutex; +static pthread_mutex_t destroyedWidgetsTableMutex; // /* // * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. // * // * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. // */ -// static MwLL* destroyedWidgetsTable; +static MwLL* destroyedWidgetsTable; -// MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { -// int i; -// pthread_mutex_lock(&destroyedWidgetsTableMutex); -// for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { -// if(self == destroyedWidgetsTable[i]) { -// pthread_mutex_unlock(&destroyedWidgetsTableMutex); -// return MwTRUE; -// } -// } -// pthread_mutex_unlock(&destroyedWidgetsTableMutex); -// return MwFALSE; -// } -// void MwLLWaylandWidgetUndestroy(MwLL self) { -// int i; -// pthread_mutex_lock(&destroyedWidgetsTableMutex); -// for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { -// if(self == destroyedWidgetsTable[i]) { -// arrdel(destroyedWidgetsTable, i); -// break; -// } -// } -// pthread_mutex_unlock(&destroyedWidgetsTableMutex); -// return; -// } -// +MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { + int i; + pthread_mutex_lock(&destroyedWidgetsTableMutex); + for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { + if(self == destroyedWidgetsTable[i]) { + pthread_mutex_unlock(&destroyedWidgetsTableMutex); + return MwTRUE; + } + } + pthread_mutex_unlock(&destroyedWidgetsTableMutex); + return MwFALSE; +} +void MwLLWaylandWidgetUndestroy(MwLL self) { + int i; + pthread_mutex_lock(&destroyedWidgetsTableMutex); + for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { + if(self == destroyedWidgetsTable[i]) { + arrdel(destroyedWidgetsTable, i); + break; + } + } + pthread_mutex_unlock(&destroyedWidgetsTableMutex); + return; +} void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { if(handle->common.user) { @@ -988,7 +987,7 @@ static void count_child(MwLL handle, MwLL child) { handle->wayland.cascading_child_num++; } -static void cascade_children(MwLL handle) { +void MwLLWaylandCascadeChildren(MwLL handle) { handle->wayland.cascading_child_num = 0; MwLLWaylandChildrenIterate(handle, count_child); @@ -1339,7 +1338,7 @@ static void MwLLEndDrawImpl(MwLL handle) { } MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); - cascade_children(handle); + MwLLWaylandCascadeChildren(handle); } } From 6f4164da0cf33aafcfdb4606acbe4d84d783f994 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 21:25:13 -0700 Subject: [PATCH 050/168] erm --- src/backend/wayland/wayland.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index d032e7d..d3fb201 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -13,11 +13,11 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; static pthread_mutex_t destroyedWidgetsTableMutex; -// /* -// * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. -// * -// * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. -// */ +/* + * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. + * + * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. + */ static MwLL* destroyedWidgetsTable; MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { @@ -862,7 +862,12 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.x = x; r->wayland.y = y; r->wayland.parent = parent; - r->wayland.valid = MwTRUE; + if(MwLLWaylandWidgetIsDestroyed(parent)) { + r->wayland.valid = MwFALSE; + return; + } else { + r->wayland.valid = MwTRUE; + } if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { @@ -1064,9 +1069,9 @@ static void MwLLDestroyImpl(MwLL handle) { printf("widget invalid\n"); } - // pthread_mutex_lock(&destroyedWidgetsTableMutex); - // arrput(destroyedWidgetsTable, handle); - // pthread_mutex_unlock(&destroyedWidgetsTableMutex); + pthread_mutex_lock(&destroyedWidgetsTableMutex); + arrput(destroyedWidgetsTable, handle); + pthread_mutex_unlock(&destroyedWidgetsTableMutex); free(handle); } From f835e41fb0bfda7ecdd622f2c2290275f594f88b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 21:34:58 -0700 Subject: [PATCH 051/168] back --- src/backend/wayland/interfaces.c | 1 + src/backend/wayland/wayland.c | 46 +++++++++++++------------------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 706318a..0d960c2 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -681,6 +681,7 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri (void)time; WAYLAND_EVENT_OP_START(self); + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; p.point = self->wayland.cur_mouse_pos; diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index d3fb201..4f832dc 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -242,7 +242,8 @@ static void xdg_surface_configure( xdg_surface_ack_configure(xdg_surface, serial); - MwLLDispatch(self, draw, NULL); + MwLLWaylandCascadeChildren(self); + // MwLLDispatch(self, draw, NULL); if(self->wayland.configured) { MwLLWaylandBufferUpdate(self, &self->wayland.framebuffer); @@ -996,7 +997,7 @@ void MwLLWaylandCascadeChildren(MwLL handle) { handle->wayland.cascading_child_num = 0; MwLLWaylandChildrenIterate(handle, count_child); - handle->wayland.do_cascading_draw = 10; + handle->wayland.do_cascading_draw = handle->wayland.cascading_child_num * 10; MwLLWaylandChildrenIterate(handle, cascade_child); } @@ -1006,6 +1007,10 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { memset(r, 0, sizeof(*r)); MwLLCreateCommon(r); + if(MwLLWaylandWidgetIsDestroyed(r)) { + MwLLWaylandWidgetUndestroy(r); + } + r->wayland.is_toplevel = parent == NULL; r->wayland.is_clipping = 0; @@ -1123,7 +1128,8 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) recursive_render(handle); - MwLLDispatch(handle, draw, NULL); + MwLLWaylandCascadeChildren(handle); + // MwLLDispatch(handle, draw, NULL); } static void actually_set_wh(MwLL handle) { @@ -1152,7 +1158,8 @@ static void actually_set_wh(MwLL handle) { MwLLWaylandFramebufferSetup(&handle->wayland); MwLLWaylandBackbufferDestroy(&handle->wayland); MwLLWaylandBackbufferSetup(&handle->wayland); - MwLLDispatch(handle, draw, NULL); + MwLLWaylandCascadeChildren(handle); + // MwLLDispatch(handle, draw, NULL); } static void MwLLSetWHImpl(MwLL handle, int w, int h) { @@ -1401,6 +1408,10 @@ static int MwLLPendingImpl(MwLL handle) { }; int pending = 0; + if(MwLLWaylandWidgetIsDestroyed(handle) || !handle->wayland.valid) { + return 0; + } + handle->wayland.resizing = 0; if(handle->wayland.setting_wh) { @@ -1433,7 +1444,8 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->wayland.dark_theme_detection) { handle->wayland.dark_theme_detection = MwFALSE; detect_dark_theme(handle); - MwLLDispatch(handle, draw, NULL); + MwLLWaylandCascadeChildren(handle); + // MwLLDispatch(handle, draw, NULL); } else { MwLLDBusPortalPoll(&wl_call_tbl.dbus, &handle->wayland.dbus, handle, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &dark_theme_listener); } @@ -1881,27 +1893,6 @@ static void MwLLEndStateChangeImpl(MwLL handle) { if(!handle->wayland.parent) handle->wayland.dark_theme_detection = MwTRUE; - if(handle->common.user) { - MwWidget w = handle->common.user; - int i; - for(i = 0; i < arrlen(w->children); i++) { - if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - MwLL child = w->children[i]->lowlevel; - child->wayland.sublevel->xdg_surface = handle->wayland.popup->xdg_surface; - // if(child->wayland.sublevel->subsurface) - // wl_subsurface_destroy(child->wayland.sublevel->subsurface); - MwLLWaylandFlush(handle); - - // child->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(child->wayland.sublevel->subcompositor, child->wayland.framebuffer.surface, handle->wayland.framebuffer.surface); - // wl_subsurface_set_desync(child->wayland.sublevel->subsurface); - // wl_subsurface_set_position(child->wayland.sublevel->subsurface, child->wayland.x, child->wayland.y); - - // wl_subsurface_place_above(child->wayland.sublevel->subsurface, handle->wayland.framebuffer.surface); - MwLLEndStateChangeImpl(w->children[i]->lowlevel); - } - } - } - recursive_render(handle); handle->wayland.events_pending = 1; @@ -1913,7 +1904,8 @@ static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { (void)toggle; /* Not Really what's supposed to happen with this function, but take this opprutunity to do the handlers that will force everything to redraw. */ - MwLLDispatch(handle, resize, NULL); + MwLLWaylandCascadeChildren(handle); + // MwLLDispatch(handle, resize, NULL); MwLLDispatch(handle, draw, NULL); } From 4d768455bc6e26929b36bdad64417650f66afcf1 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 22:29:05 -0700 Subject: [PATCH 052/168] finnish --- CMakeLists.txt | 1 + examples/vkdemos/vulkan.c | 4 +-- include/Mw/LowLevel/Wayland.h | 15 +++++++++ pl/rules.pl | 1 + src/backend/wayland/buffer.c | 34 +++++++++++++++++++ src/backend/wayland/interfaces.c | 56 ++++++++++++++++++++++++++++---- src/backend/wayland/wayland.c | 43 +++++++++++++++++------- src/widget/opengl.c | 6 ++++ src/widget/vulkan.c | 2 ++ 9 files changed, 142 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 534614f..1ec1ed8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,7 @@ if(MW_USE_WAYLAND) scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1") + scan_wayland_protocol("staging" "fifo" "-v1") scan_wayland_protocol_from_file("wlr-layer-shell" "wlr-layer-shell-unstable-v1.xml") target_sources( diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 9060a97..6015415 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -257,8 +257,8 @@ void vulkan_setup(MwWidget handle) { swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh}, swapchainCreateInfo.imageArrayLayers = 1, swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; // th is how we specify no transformation. swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index f7102ce..5e43c34 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -207,6 +207,7 @@ MwInline int wayland_load_funcs() { #include "Wayland/relative-pointer-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h" #include "Wayland/wlr-layer-shell-client-protocol.h" +#include "Wayland/fifo-client-protocol.h" #endif typedef struct wayland_protocol { @@ -266,6 +267,7 @@ struct _MwLLWaylandShmBuffer { struct wl_buffer* shm_buffer_back; struct wl_surface* surface; struct wl_output* output; + struct wp_fifo_v1* fifo; MwU8* buf; MwU8* buf_back; @@ -435,6 +437,8 @@ struct _MwLLWayland { struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; struct _MwLLWaylandShmBuffer* icon; + MwBool fifo_wait; + MwBool disable_fifo; MwLLPixmap icon_pixmap; @@ -472,6 +476,17 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland); /* Destroy the backbuffer */ void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* handle); +/* Bind a wp_fifo_v1 object to `buffer`'s surface, if wp_fifo_manager_v1 is available and it doesn't have one already. */ +void MwLLWaylandFifoSurfaceSetup(struct _MwLLWayland* wayland, struct _MwLLWaylandShmBuffer* buffer); +/* Destroy `buffer`'s wp_fifo_v1 object, if any. */ +void MwLLWaylandFifoSurfaceDestroy(struct _MwLLWaylandShmBuffer* buffer); +/* Commit `buffer`'s surface, constraining the update to the next display refresh via wp_fifo_v1 if bound. */ +void MwLLWaylandFifoCommit(struct _MwLLWaylandShmBuffer* buffer); + +#ifdef MW_VULKAN +#warning Wayland backend currently disabled by default when Vulkan enabled. Use with caution (MW_BACKEND=wayland to override). +#endif + void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height); void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer); void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer); diff --git a/pl/rules.pl b/pl/rules.pl index 986ee98..6c4df63 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -66,6 +66,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); + scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); $gl_libs = "-lGL -lGLU"; diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index df1de79..3ee5e3c 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -1,5 +1,39 @@ #include #include +#include "../../../external/stb_ds.h" + +/* Bind a wp_fifo_v1 object to `buffer`'s surface, if wp_fifo_manager_v1 is available and it doesn't have one already. */ +void MwLLWaylandFifoSurfaceSetup(struct _MwLLWayland* wayland, struct _MwLLWaylandShmBuffer* buffer) { + wayland_protocol_t* fifo_manager; + + if(buffer->fifo || !buffer->surface) { + return; + } + + fifo_manager = shget(wayland->wl_protocol_map, wp_fifo_manager_v1_interface.name); + if(!fifo_manager) { + return; + } + + buffer->fifo = wp_fifo_manager_v1_get_fifo(fifo_manager->context, buffer->surface); +} + +/* Destroy `buffer`'s wp_fifo_v1 object, if any. */ +void MwLLWaylandFifoSurfaceDestroy(struct _MwLLWaylandShmBuffer* buffer) { + if(buffer->fifo) { + wp_fifo_v1_destroy(buffer->fifo); + buffer->fifo = NULL; + } +} + +/* Commit `buffer`'s surface, constraining the update to the next display refresh via wp_fifo_v1 if bound. */ +void MwLLWaylandFifoCommit(struct _MwLLWaylandShmBuffer* buffer) { + if(buffer->fifo) { + wp_fifo_v1_set_barrier(buffer->fifo); + wp_fifo_v1_wait_barrier(buffer->fifo); + } + wl_surface_commit(buffer->surface); +} void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 0d960c2..9ce4261 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -19,6 +19,35 @@ static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat); static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); +/* Recursively dispatch a key event to a widget and its children */ +static void recursive_dispatch_key(MwLL handle, int* k) { + MwWidget h = (MwWidget)handle->common.user; + MwLLDispatch(handle, key, k); + if(h) { + int i; + for(i = 0; i < arrlen(h->children); i++) { + MwLLDispatch(h->children[i]->lowlevel, key, k); + if(arrlen(h->children[i]->children) > 0) { + recursive_dispatch_key(h->children[i]->lowlevel, k); + } + } + } +}; +/* Recursively dispatch a key released event to a widget and its children */ +static void recursive_dispatch_key_released(MwLL handle, int* k) { + MwWidget h = (MwWidget)handle->common.user; + MwLLDispatch(handle, key_released, k); + if(h) { + int i; + for(i = 0; i < arrlen(h->children); i++) { + MwLLDispatch(h->children[i]->lowlevel, key_released, k); + if(arrlen(h->children[i]->children) > 0) { + recursive_dispatch_key_released(h->children[i]->lowlevel, k); + } + } + } +}; + /* Recursively dispatch a move event to a widget and its children */ static void recursive_dispatch_move(MwLL handle, MwMouse* p) { MwWidget h = (MwWidget)handle->common.user; @@ -923,15 +952,11 @@ static void keyboard_key(void* data, if(key != -1) { if(state == WL_KEYBOARD_KEY_STATE_PRESSED) { - MwLL topmost_parent = self; - while(topmost_parent->wayland.parent) { - MwLLDispatch(topmost_parent, key, &key); - topmost_parent = topmost_parent->wayland.parent; - } + recursive_dispatch_key(self, &key); self->wayland.holding_key = MwTRUE; self->wayland.last_pressed_key = key; } else { - MwLLDispatch(self, key_released, &key); + recursive_dispatch_key_released(self, &key); self->wayland.holding_key = MwFALSE; } self->wayland.start_time = MwTimeGetTick(); @@ -1193,6 +1218,24 @@ static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, waylan (void)data; } +/* wp_fifo_manager_v1 setup function */ +static wayland_protocol_t* wp_fifo_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + (void)version; + proto->listener = NULL; + proto->context = wl_registry_bind(wayland->registry, name, &wp_fifo_manager_v1_interface, 1); + + return proto; +} + +static void wp_fifo_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + (void)wayland; + if(data->context) { + wp_fifo_manager_v1_destroy(data->context); + } + free(data); +} + /* zxdg_decoration_manager_v1 setup function */ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); @@ -1295,6 +1338,7 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zwp_pointer_constraints_v1); WL_INTERFACE(zwp_relative_pointer_manager_v1); WL_INTERFACE(xdg_wm_base); + WL_INTERFACE(wp_fifo_manager_v1); WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(wp_viewporter); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 4f832dc..433001b 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -242,8 +242,7 @@ static void xdg_surface_configure( xdg_surface_ack_configure(xdg_surface, serial); - MwLLWaylandCascadeChildren(self); - // MwLLDispatch(self, draw, NULL); + MwLLDispatch(self, draw, NULL); if(self->wayland.configured) { MwLLWaylandBufferUpdate(self, &self->wayland.framebuffer); @@ -260,7 +259,11 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { // Yes this is needed every time, it's how we fix weston. if(self->wayland.configured) wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - wl_surface_commit(buffer->surface); + if(self->wayland.fifo_wait) { + MwLLWaylandFifoCommit(buffer); + } else { + wl_surface_commit(buffer->surface); + } } } } @@ -309,7 +312,9 @@ static void setup_toplevel(MwLL r, int x, int y) { /* Create a wl_surface, a xdg_surface and a xdg_toplevel */ r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); r->wayland.backbuffer.surface = wl_compositor_create_surface(r->wayland.compositor); - r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.backbuffer); + r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); wl_subsurface_set_desync(r->wayland.toplevel->ssurface); r->wayland.toplevel->xdg_surface = @@ -384,6 +389,8 @@ static void destroy_toplevel(MwLL r) { wl_pointer_destroy(r->wayland.pointer); wl_keyboard_destroy(r->wayland.keyboard); + MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); + MwLLWaylandFifoSurfaceDestroy(&r->wayland.backbuffer); wl_surface_destroy(r->wayland.framebuffer.surface); free(r->wayland.toplevel); @@ -422,6 +429,7 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { } r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); r->wayland.xkb_keymap = parent->wayland.xkb_keymap; r->wayland.xkb_state = parent->wayland.xkb_state; @@ -546,6 +554,7 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { r->wayland.xkb_state = topmost_parent->wayland.xkb_state; r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); r->wayland.popup->xdg_surface = xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface); @@ -587,6 +596,8 @@ static void destroy_popup(MwLL r) { xdg_positioner_destroy(r->wayland.popup->xdg_positioner); + MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); + wl_surface_destroy(r->wayland.framebuffer.surface); wl_registry_destroy(r->wayland.registry); @@ -670,6 +681,7 @@ static void setup_layer_surface(MwLL r, int x, int y, int width, int height) { r->wayland.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); r->wayland.layer_surface->surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, r->wayland.framebuffer.surface, NULL, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "milsko-surfaces"); @@ -700,6 +712,8 @@ static void destroy_layer_surface(MwLL r) { zxdg_decoration_manager_v1_destroy(dec->manager); } + MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); + wl_surface_destroy(r->wayland.framebuffer.surface); wl_compositor_destroy(r->wayland.compositor); @@ -1128,8 +1142,7 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) recursive_render(handle); - MwLLWaylandCascadeChildren(handle); - // MwLLDispatch(handle, draw, NULL); + MwLLDispatch(handle, draw, NULL); } static void actually_set_wh(MwLL handle) { @@ -1158,8 +1171,7 @@ static void actually_set_wh(MwLL handle) { MwLLWaylandFramebufferSetup(&handle->wayland); MwLLWaylandBackbufferDestroy(&handle->wayland); MwLLWaylandBackbufferSetup(&handle->wayland); - MwLLWaylandCascadeChildren(handle); - // MwLLDispatch(handle, draw, NULL); + MwLLDispatch(handle, draw, NULL); } static void MwLLSetWHImpl(MwLL handle, int w, int h) { @@ -1444,8 +1456,7 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->wayland.dark_theme_detection) { handle->wayland.dark_theme_detection = MwFALSE; detect_dark_theme(handle); - MwLLWaylandCascadeChildren(handle); - // MwLLDispatch(handle, draw, NULL); + MwLLDispatch(handle, draw, NULL); } else { MwLLDBusPortalPoll(&wl_call_tbl.dbus, &handle->wayland.dbus, handle, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &dark_theme_listener); } @@ -1474,10 +1485,12 @@ static int MwLLPendingImpl(MwLL handle) { return pending; } + if(!handle->wayland.disable_fifo) handle->wayland.fifo_wait = MwTRUE; MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } + if(!handle->wayland.disable_fifo) handle->wayland.fifo_wait = MwFALSE; return handle->wayland.force_render || handle->wayland.events_pending || pending; } @@ -1494,9 +1507,11 @@ static void MwLLNextEventImpl(MwLL handle) { } if(handle->wayland.force_render) { + handle->wayland.fifo_wait = MwTRUE; MwLLDispatch(handle, draw, NULL); if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); handle->wayland.force_render = 0; + handle->wayland.fifo_wait = MwFALSE; } if(handle->wayland.events_pending) { handle->wayland.events_pending = 0; @@ -1904,7 +1919,7 @@ static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { (void)toggle; /* Not Really what's supposed to happen with this function, but take this opprutunity to do the handlers that will force everything to redraw. */ - MwLLWaylandCascadeChildren(handle); + MwLLDispatch(handle, draw, NULL); // MwLLDispatch(handle, resize, NULL); MwLLDispatch(handle, draw, NULL); } @@ -1958,10 +1973,14 @@ static int MwLLWaylandCallInitImpl(void) { } else { loadWayland |= (strcmp(mw_backend_env, "wayland") == 0); } + } - } else if(getenv("WAYLAND_DISPLAY")) { + /* NOTE: when vulkan is enabled, refuse to default to wayland. Remove this if I ever get Vulkan widget working with the new surfaces system. */ +#ifndef MW_VULKAN + else if(getenv("WAYLAND_DISPLAY")) { loadWayland |= (getenv("WAYLAND_DISPLAY") != NULL); } +#endif #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 30a1cee..9e1b91e 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -240,6 +240,12 @@ static int wcreate(MwWidget handle) { waylandopengl_t* o = r = malloc(sizeof(*o)); int gbm_format = 0; EGLConfig egl_configs[1024]; + MwWidget topmost_parent = handle; + + /* Disable fifo waiting when we have an OpenGL widget */ + while(topmost_parent->parent) topmost_parent = topmost_parent->parent; + topmost_parent->lowlevel->wayland.disable_fifo = MwTRUE; + memset(o, 0, sizeof(waylandopengl_t)); o->gllib = MwDynamicOpen("libEGL.so"); diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index f4c5340..acffda3 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -240,6 +240,8 @@ static int vulkan_instance_setup(MwWidget handle, vulkan_t* o) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { + MwWidget topmost_parent = handle; + arrput(o->enabledExtensions, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); /* take this opprutunity to set the widget to always render */ MwWaylandVulkan = MwTRUE; From 8fc51bd1e4d58dc7f84086b761ff5e9934b18ab0 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 13 Sep 2026 12:21:05 +0900 Subject: [PATCH 053/168] unicode fix --- examples/basic/filechooser.c | 4 +- examples/vkdemos/vulkan.c | 4 +- include/Mw/Abstract/CharSet.h | 4 +- include/Mw/Unicode.h | 40 +++++++++++- pl/rules.pl | 3 +- src/abstract/charset.c | 42 ++---------- src/abstract/directory.c | 6 +- src/backend/cairo.c | 12 ++-- src/dialog/filechooser.c | 4 +- src/text/gdi.c | 46 +++++++++---- src/unicode.c | 118 ++++++++++++++++++++++++++++++++++ 11 files changed, 218 insertions(+), 65 deletions(-) diff --git a/examples/basic/filechooser.c b/examples/basic/filechooser.c index 6ad5636..a9a5ec0 100644 --- a/examples/basic/filechooser.c +++ b/examples/basic/filechooser.c @@ -16,10 +16,12 @@ void MWAPI ok(MwWidget handle, void* user, void* call) { #ifdef BUG msgbox_wait = MwFALSE; #endif + + MwDestroyWidget(mb); } void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { - mb = MwMessageBox(handle, call_data, "File chosen", MwMB_ICONERROR | MwMB_BUTTONOK); + mb = MwMessageBox(window, call_data, "File chosen", MwMB_ICONERROR | MwMB_BUTTONOK); (void)user_data; diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 6015415..9060a97 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -257,8 +257,8 @@ void vulkan_setup(MwWidget handle) { swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh}, swapchainCreateInfo.imageArrayLayers = 1, swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; // th is how we specify no transformation. swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/include/Mw/Abstract/CharSet.h b/include/Mw/Abstract/CharSet.h index f0a42f7..0d92ec4 100644 --- a/include/Mw/Abstract/CharSet.h +++ b/include/Mw/Abstract/CharSet.h @@ -11,9 +11,9 @@ extern "C" { #endif -MWDECL char* MWAPI MwACPToUTF8(const char* input); +MWDECL char* MWAPI MwACPTextToUTF8Text(const char* input); -MWDECL char* MWAPI MwUTF8ToACP(const char* input); +MWDECL char* MWAPI MwUTF8TextToACPText(const char* input); #ifdef __cplusplus } diff --git a/include/Mw/Unicode.h b/include/Mw/Unicode.h index 32edeaa..781fad2 100644 --- a/include/Mw/Unicode.h +++ b/include/Mw/Unicode.h @@ -20,6 +20,22 @@ extern "C" { */ MWDECL int MWAPI MwUTF8ToUTF32(const char* input, int* output); +/*! + * @brief Converts UTF-8 to UTF-16 + * @brief input Input + * @brief output Output + * @return Bytes this multibyte takes + * @note Output gets NUL terminated + */ +MWDECL int MWAPI MwUTF8ToUTF16(const char* input, wchar_t* output); + +/*! + * @brief Converts UTF-8 text to UTF-16 text + * @brief input Input + * @return Output + */ +MWDECL wchar_t* MWAPI MwUTF8TextToUTF16Text(const char* input); + /*! * @brief Calculates UTF-8 string length * @brief input Input @@ -38,11 +54,33 @@ MWDECL int MWAPI MwUTF8Length(const char* input); */ MWDECL int MWAPI MwUTF8Copy(const char* src, int srcskip, char* dst, int dstskip, int len); +/*! + * @brief Returns the count current word takes + * @brief input Input + * @return Count + */ +MWDECL int MWAPI MwUTF16Count(const wchar_t* input); + +/*! + * @brief Converts UTF-16 to UTF-8 + * @brief input Input + * @brief output Output + * @return Bytes this multibyte takes + */ +MWDECL int MWAPI MwUTF16ToUTF8(const wchar_t* input, char* output); + +/*! + * @brief Converts UTF-16 text to UTF-8 text + * @brief input Input + * @return Output + */ +MWDECL char* MWAPI MwUTF16TextToUTF8Text(const wchar_t* input); + /*! * @brief Converts UTF-32 to UTF-8 * @brief input Input * @brief output Output - * @return Bytes this wide byte takes + * @return Bytes this multibyte takes */ MWDECL int MWAPI MwUTF32ToUTF8(int input, char* output); diff --git a/pl/rules.pl b/pl/rules.pl index 6c4df63..0fe264c 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -67,7 +67,8 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); scan_wayland_protocol("staging", "fifo", "-v1"); - scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); + scan_wayland_protocol_from_file("wlr-layer-shell", + "wlr-layer-shell-unstable-v1.xml"); $gl_libs = "-lGL -lGLU"; } diff --git a/src/abstract/charset.c b/src/abstract/charset.c index 3bd7625..2c339d5 100644 --- a/src/abstract/charset.c +++ b/src/abstract/charset.c @@ -1,21 +1,16 @@ #include -#ifndef CP_UTF8 -#define CP_UTF8 65001 -#endif - -char* MwACPToUTF8(const char* input) { +char* MwACPTextToUTF8Text(const char* input) { #if defined(_WIN32) && defined(MW_HAS_WCHAR) int mbbytes = (strlen(input) + 1) * 4; int wbytes = 0; int len; wchar_t* wout; - char* mbout = malloc(mbbytes); + char* mbout; wbytes = MultiByteToWideChar(CP_ACP, 0, input, strlen(input), NULL, 0) * sizeof(wchar_t); if(wbytes == 0) { - free(mbout); return MwStringDuplicate(input); } @@ -23,23 +18,15 @@ char* MwACPToUTF8(const char* input) { len = wbytes / sizeof(wchar_t); memset(wout, 0, wbytes); - memset(mbout, 0, mbbytes); len = MultiByteToWideChar(CP_ACP, 0, input, strlen(input), wout, len); if(len == 0) { - free(mbout); free(wout); return MwStringDuplicate(input); } wout[len] = 0; - len = WideCharToMultiByte(CP_UTF8, 0, wout, len, mbout, mbbytes, 0, 0); - if(len == 0) { - free(mbout); - free(wout); - return MwStringDuplicate(input); - } - mbout[len] = 0; + mbout = MwUTF16TextToUTF8Text(wout); free(wout); @@ -49,7 +36,7 @@ char* MwACPToUTF8(const char* input) { #endif } -char* MwUTF8ToACP(const char* input) { +char* MwUTF8TextToACPText(const char* input) { #if defined(_WIN32) && defined(MW_HAS_WCHAR) int mbbytes = (strlen(input) + 1) * 4; int wbytes = 0; @@ -58,25 +45,8 @@ char* MwUTF8ToACP(const char* input) { wchar_t* wout; char* mbout = malloc(mbbytes); - wbytes = MultiByteToWideChar(CP_UTF8, 0, input, strlen(input), NULL, 0) * sizeof(wchar_t); - if(wbytes == 0) { - free(mbout); - return MwStringDuplicate(input); - } - - wout = malloc(wbytes + sizeof(wchar_t)); - len = wbytes / sizeof(wchar_t); - - memset(wout, 0, wbytes); - memset(mbout, 0, mbbytes); - - len = MultiByteToWideChar(CP_UTF8, 0, input, strlen(input), wout, len); - if(len == 0) { - free(mbout); - free(wout); - return MwStringDuplicate(input); - } - wout[len] = 0; + wout = MwUTF8TextToUTF16Text(input); + len = wcslen(wout); len = WideCharToMultiByte(CP_ACP, 0, wout, len, mbout, mbbytes, 0, 0); if(len == 0) { diff --git a/src/abstract/directory.c b/src/abstract/directory.c index 977f2f5..d7b364f 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -184,8 +184,8 @@ static void MwDirectoryJoinSingle(char* target, char* p) { b[0] = DIRSEP; b[1] = 0; - MwStringConcat(target, b); - MwStringConcat(target, p); + strcat(target, b); + strcat(target, p); } for(i = strlen(target) - 1; i >= 0; i--) { @@ -201,7 +201,7 @@ static void MwDirectoryJoinSingle(char* target, char* p) { b[0] = DIRSEP; b[1] = 0; - MwStringConcat(target, b); + strcat(target, b); } } diff --git a/src/backend/cairo.c b/src/backend/cairo.c index d70de1b..65380fb 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -212,8 +212,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -257,10 +257,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/dialog/filechooser.c b/src/dialog/filechooser.c index 138fc6c..b1fcc9b 100644 --- a/src/dialog/filechooser.c +++ b/src/dialog/filechooser.c @@ -469,7 +469,7 @@ static void scan(MwWidget handle, const char* path, int record) { if(strcmp(fc->entries[i]->name, ".") == 0 || strcmp(fc->entries[i]->name, "..") == 0) continue; if(fc->entries[i]->type == MwDIRECTORY_DIRECTORY) { char date[128]; - char* n = MwACPToUTF8(fc->entries[i]->name); + char* n = MwACPTextToUTF8Text(fc->entries[i]->name); MwStringTime(date, fc->entries[i]->mtime); @@ -487,7 +487,7 @@ static void scan(MwWidget handle, const char* path, int record) { if(fc->entries[i]->type == MwDIRECTORY_FILE && !fc->dir_only) { char date[128]; char size[128]; - char* n = MwACPToUTF8(fc->entries[i]->name); + char* n = MwACPTextToUTF8Text(fc->entries[i]->name); MwStringTime(date, fc->entries[i]->mtime); MwStringSize(size, fc->entries[i]->size); diff --git a/src/text/gdi.c b/src/text/gdi.c index 97e6870..91ccac9 100644 --- a/src/text/gdi.c +++ b/src/text/gdi.c @@ -5,6 +5,8 @@ static HANDLE(WINAPI* _AddFontMemResourceEx)(PVOID pFileView, DWORD cjSize, PVOI static BOOL(WINAPI* _RemoveFontMemResourceEx)(HANDLE h) = NULL; static HANDLE WINAPI _AddFontMemResourceExPolyFill(PVOID pFileView, DWORD cjSize, PVOID pvResrved, DWORD* pNumFonts); static BOOL WINAPI _RemoveFontMemResourceExPolyFill(HANDLE h); +static BOOL(WINAPI* _TextOutW)(HDC hdc, int x, int y, LPCWSTR lpString, int c); +static BOOL(WINAPI* _GetTextExtentPoint32W)(HDC hdc, LPCWSTR lpString, int c, LPSIZE psizl); struct _MwFLFont { HANDLE handle; @@ -19,8 +21,9 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c HBITMAP hbm; RGBQUAD* bits = NULL; HDC hmdc; - char* t = MwUTF8ToACP(text); unsigned char* px; + char* t; + wchar_t* t16; int y, x; MwRect r; MwLLPixmap p; @@ -33,14 +36,20 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c int old_bkmode = SetBkMode(handle->lowlevel->gdi.hDC, TRANSPARENT); COLORREF old_color = SetTextColor(handle->lowlevel->gdi.hDC, RGB(color->common.red, color->common.green, color->common.blue)); - TextOut(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t, strlen(t)); + if(_TextOutW == NULL) { + t = MwUTF8TextToACPText(text); + TextOutA(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t, strlen(t)); + free(t); + } else { + t16 = MwUTF8TextToUTF16Text(text); + TextOutW(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t16, wcslen(t16)); + free(t16); + } SetTextColor(handle->lowlevel->gdi.hDC, old_color); SetBkMode(handle->lowlevel->gdi.hDC, old_bkmode); SelectObject(handle->lowlevel->gdi.hDC, old_font); - free(t); - return 0; } @@ -64,7 +73,15 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c SelectObject(hmdc, hbm); SelectObject(hmdc, ttf->font); - TextOut(hmdc, 0, 0, t, strlen(t)); + if(_TextOutW == NULL) { + t = MwUTF8TextToACPText(text); + TextOutA(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t, strlen(t)); + free(t); + } else { + t16 = MwUTF8TextToUTF16Text(text); + TextOutW(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t16, wcslen(t16)); + free(t16); + } DeleteDC(hmdc); @@ -90,18 +107,22 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c free(px); DeleteObject(hbm); - free(t); return 0; } static int GDI_MwTextWidth(MwFLFont ttf, const char* text) { - char* t = MwUTF8ToACP(text); - SIZE sz; + SIZE sz; - GetTextExtentPoint32(ttf->dc, t, strlen(t), &sz); - - free(t); + if(_GetTextExtentPoint32W == NULL) { + char* t = MwUTF8TextToACPText(text); + GetTextExtentPoint32A(ttf->dc, t, strlen(t), &sz); + free(t); + } else { + wchar_t* t16 = MwUTF8TextToUTF16Text(text); + _GetTextExtentPoint32W(ttf->dc, t16, wcslen(t16), &sz); + free(t16); + } return sz.cx; } @@ -255,6 +276,9 @@ int MwFL_GDISetup(void) { if(!_RemoveFontMemResourceEx) { _RemoveFontMemResourceEx = _RemoveFontMemResourceExPolyFill; } + + _TextOutW = (void*)GetProcAddress(gdilib, "TextOutW"); + _GetTextExtentPoint32W = (void*)GetProcAddress(gdilib, "GetTextExtentPoint32W"); } MwFLDrawText = GDI_MwDrawText; diff --git a/src/unicode.c b/src/unicode.c index f6c7685..979fd31 100644 --- a/src/unicode.c +++ b/src/unicode.c @@ -58,6 +58,50 @@ int MwUTF8ToUTF32(const char* input, int* output) { return b; } +int MwUTF8ToUTF16(const char* input, wchar_t* output) { + int o; + int n = MwUTF8ToUTF32(input, &o); + + if(n == 0 || n >= 0x10ffff) return 0; + + if(o < 0x10000) { + output[0] = o; + output[1] = 0; + } else { + output[0] = (o - 0x10000) / 0x400 + 0xd800; + output[1] = (o - 0x10000) % 0x400 + 0xdc00; + output[2] = 0; + } + + return n; +} + +wchar_t* MwUTF8TextToUTF16Text(const char* input) { + wchar_t* o = malloc((MwUTF8Length(input) * 2 + 1) * sizeof(*o)); + int n = 0; + wchar_t buffer[3]; + + o[0] = 0; + + while(input[0] != 0) { + int new = MwUTF8ToUTF16(input, buffer); + + if(new == 0) { + free(o); + return NULL; + } + + memcpy(o + n, buffer, wcslen(buffer) * sizeof(*o)); + + input += new; + n += wcslen(buffer); + } + + o[n] = 0; + + return o; +} + int MwUTF8Length(const char* input) { int out; int len = 0; @@ -97,6 +141,80 @@ int MwUTF8Copy(const char* src, int srcskip, char* dst, int dstskip, int len) { return total; } +static int is_u16_high(wchar_t ch) { + return 0xd800 <= ch && ch < 0xdc00; +} + +static int is_u16_low(wchar_t ch) { + return 0xdc00 <= ch && ch < 0xe000; +} + +int MwUTF16Count(const wchar_t* input) { + if(is_u16_high(input[0])) { + if(is_u16_low(input[1])) { + return 2; + } else if(input[1] == 0) { + return 2; + } else { + return 0; + } + } else if(is_u16_low(input[0])) { + if(input[1] == 0) { + return 2; + } else { + return 0; + } + } else { + return 1; + } +} + +int MwUTF16ToUTF8(const wchar_t* input, char* output) { + if(is_u16_high(input[0])) { + if(is_u16_low(input[1])) { + return MwUTF32ToUTF8(0x10000 + (CAST_I32(input[0]) - 0xd800) * 0x400 + (CAST_I32(input[1]) - 0xdc00), output); + } else if(input[1] == 0) { + return MwUTF32ToUTF8(input[0], output); + } else { + return 0; + } + } else if(is_u16_low(input[0])) { + if(input[1] == 0) { + return MwUTF32ToUTF8(input[0], output); + } else { + return 0; + } + } else { + return MwUTF32ToUTF8(input[0], output); + } +} + +char* MwUTF16TextToUTF8Text(const wchar_t* input) { + char* o = malloc(4 * wcslen(input) + 1); + int n = 0; + char buffer[4]; + + o[0] = 0; + + while(input[0]) { + int new = MwUTF16ToUTF8(input, buffer); + + if(new == 0) { + free(o); + return NULL; + } + + memcpy(o + n, buffer, new); + + input += MwUTF16Count(input); + n += new; + } + + o[n] = 0; + + return o; +} + int MwUTF32ToUTF8(int input, char* output) { if(input < 128) { output[0] = input; From d98d2e15cef86ee8848975d81e6f4ea7941d0b4d Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 13 Sep 2026 00:17:18 -0700 Subject: [PATCH 054/168] fix submenus --- include/Mw/LowLevel/Wayland.h | 5 +- pl/rules.pl | 2 +- src/backend/wayland/interfaces.c | 122 ++++++++++++++----------------- src/backend/wayland/wayland.c | 14 ++-- 4 files changed, 67 insertions(+), 76 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 5e43c34..234e3e8 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -239,8 +239,9 @@ struct _MwLLWaylandTopLevel { }; struct _MwLLWaylandSublevel { - - MwLL parent; + MwLL parent; + struct wl_subcompositor* subcompositor; + struct wl_subsurface* subsurface; struct xdg_surface* xdg_surface; }; diff --git a/pl/rules.pl b/pl/rules.pl index 0fe264c..afc9ef9 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -66,7 +66,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); - scan_wayland_protocol("staging", "fifo", "-v1"); + scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 9ce4261..a69ad1b 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -587,21 +587,21 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time p.point = self->wayland.cur_mouse_pos; MwLLDispatch(self, move, &p); wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); - } - for(i = 0; i < arrlen(currentlyHeldWidgets); i++) { - MwLL new_topmost = currentlyHeldWidgets[i]; - p.point = topmost_parent->wayland.cur_mouse_pos; - while(new_topmost->wayland.parent) { - p.point.x -= new_topmost->wayland.x; - p.point.y -= new_topmost->wayland.y; - new_topmost = new_topmost->wayland.parent; + + for(i = 0; i < arrlen(currentlyHeldWidgets); i++) { + MwLL new_topmost = currentlyHeldWidgets[i]; + p.point = topmost_parent->wayland.cur_mouse_pos; + while(new_topmost->wayland.parent) { + p.point.x -= new_topmost->wayland.x; + p.point.y -= new_topmost->wayland.y; + new_topmost = new_topmost->wayland.parent; + } + + MwLLDispatch(currentlyHeldWidgets[i], move, &p); } - - MwLLDispatch(currentlyHeldWidgets[i], move, &p); + MwLLWaylandCascadeChildren(self); } - MwLLWaylandCascadeChildren(self); - WAYLAND_EVENT_OP_END(self); }; @@ -704,6 +704,7 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri MwMouse p; MwLL topmost_parent = self; int i; + MwBool inArea = MwFALSE; (void)wl_pointer; (void)serial; @@ -711,45 +712,54 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri WAYLAND_EVENT_OP_START(self); - while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; + if(self->wayland.type != MwLL_WAYLAND_POPUP) { + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; + } p.point = self->wayland.cur_mouse_pos; - switch(button) { - case BTN_LEFT: - p.button = MwMOUSE_LEFT; - break; - case BTN_MIDDLE: - p.button = MwMOUSE_MIDDLE; - break; - case BTN_RIGHT: - p.button = MwMOUSE_RIGHT; - break; + if(self->wayland.framebuffer.surface) { + inArea |= self->wayland.framebuffer.surface == curSurface; } - self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; - switch(state) { - case WL_POINTER_BUTTON_STATE_PRESSED: - MwLLDispatch(self, down, &p); - break; - case WL_POINTER_BUTTON_STATE_RELEASED: - MwLLDispatch(self, up, &p); - break; + if(self->wayland.backbuffer.surface) { + inArea |= self->wayland.backbuffer.surface == curSurface; } + if(inArea) { + switch(button) { + case BTN_LEFT: + p.button = MwMOUSE_LEFT; + break; + case BTN_MIDDLE: + p.button = MwMOUSE_MIDDLE; + break; + case BTN_RIGHT: + p.button = MwMOUSE_RIGHT; + break; + } + self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; + // switch(state) { + // case WL_POINTER_BUTTON_STATE_PRESSED: + // MwLLDispatch(self, down, &p); + // break; + // case WL_POINTER_BUTTON_STATE_RELEASED: + // MwLLDispatch(self, up, &p); + // break; + // } - for(i = 0; i < arrlen(self->wayland.currentlyHeldWidgets); i++) { - arrdel(self->wayland.currentlyHeldWidgets, i); + for(i = 0; i < arrlen(self->wayland.currentlyHeldWidgets); i++) { + arrdel(self->wayland.currentlyHeldWidgets, i); + } + mouse_dispatch(self, p, state); + + if(!self->wayland.has_decorations && self->wayland.do_csd) { + if(state != WL_POINTER_BUTTON_STATE_RELEASED) + xdg_borderless_step_mdown(self, p, serial); + else + xdg_borderless_step_mup(self, p, serial); + } + + MwLLForceRender(self); } - mouse_dispatch(self, p, state); - - if(!self->wayland.has_decorations && self->wayland.do_csd) { - if(state != WL_POINTER_BUTTON_STATE_RELEASED) - xdg_borderless_step_mdown(self, p, serial); - else - xdg_borderless_step_mup(self, p, serial); - } - - MwLLForceRender(self); - WAYLAND_EVENT_OP_END(self); }; @@ -1169,7 +1179,7 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } else { - // wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } return NULL; @@ -1180,7 +1190,7 @@ static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, way if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wl_subcompositor_destroy(wayland->toplevel->scompositor); } else { - // wl_subcompositor_destroy(wayland->sublevel->subcompositor); + wl_subcompositor_destroy(wayland->sublevel->subcompositor); } } @@ -1218,24 +1228,6 @@ static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, waylan (void)data; } -/* wp_fifo_manager_v1 setup function */ -static wayland_protocol_t* wp_fifo_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { - wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); - (void)version; - proto->listener = NULL; - proto->context = wl_registry_bind(wayland->registry, name, &wp_fifo_manager_v1_interface, 1); - - return proto; -} - -static void wp_fifo_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; - if(data->context) { - wp_fifo_manager_v1_destroy(data->context); - } - free(data); -} - /* zxdg_decoration_manager_v1 setup function */ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); @@ -1338,7 +1330,6 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zwp_pointer_constraints_v1); WL_INTERFACE(zwp_relative_pointer_manager_v1); WL_INTERFACE(xdg_wm_base); - WL_INTERFACE(wp_fifo_manager_v1); WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(wp_viewporter); @@ -1352,7 +1343,6 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(wp_viewporter); WL_INTERFACE(wl_subcompositor); WL_INTERFACE(wl_seat); - WL_INTERFACE(wl_seat); } else { WL_INTERFACE(wl_subcompositor); } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 433001b..3c2d9bd 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -417,8 +417,10 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { if(parent->wayland.type == MwLL_WAYLAND_TOPLEVEL) { r->wayland.sublevel->xdg_surface = parent->wayland.toplevel->xdg_surface; - } else { + } else if(parent->wayland.type == MwLL_WAYLAND_SUBLEVEL) { r->wayland.sublevel->xdg_surface = parent->wayland.sublevel->xdg_surface; + } else if(parent->wayland.type == MwLL_WAYLAND_POPUP) { + r->wayland.sublevel->xdg_surface = parent->wayland.popup->xdg_surface; } wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); @@ -427,9 +429,7 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { raise(SIGTRAP); return; } - r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor); - MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); r->wayland.xkb_keymap = parent->wayland.xkb_keymap; r->wayland.xkb_state = parent->wayland.xkb_state; @@ -542,10 +542,10 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { xdg_positioner_set_size(r->wayland.popup->xdg_positioner, r->wayland.ww, r->wayland.wh); xdg_positioner_set_anchor_rect( r->wayland.popup->xdg_positioner, - r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); - // xdg_positioner_set_offset( - // r->wayland.popup->xdg_positioner, - // r->wayland.x, r->wayland.y); + topmost_parent->wayland.x, topmost_parent->wayland.y, r->wayland.ww, r->wayland.wh); + xdg_positioner_set_offset( + r->wayland.popup->xdg_positioner, + r->wayland.x, r->wayland.y); xdg_positioner_set_anchor(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_NONE); xdg_positioner_set_gravity(r->wayland.popup->xdg_positioner, XDG_POSITIONER_GRAVITY_NONE); From d5e6847334196cc2b8f623a276361283e8ccc274 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 13 Sep 2026 00:20:08 -0700 Subject: [PATCH 055/168] fix accidental subsurface reinclusion --- include/Mw/LowLevel/Wayland.h | 4 +--- src/backend/wayland/interfaces.c | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 234e3e8..3e9d671 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -239,9 +239,7 @@ struct _MwLLWaylandTopLevel { }; struct _MwLLWaylandSublevel { - MwLL parent; - struct wl_subcompositor* subcompositor; - struct wl_subsurface* subsurface; + MwLL parent; struct xdg_surface* xdg_surface; }; diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index a69ad1b..73ac8b1 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -1178,8 +1178,6 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan (void)version; if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); - } else { - wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } return NULL; @@ -1189,8 +1187,6 @@ static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, way (void)data; if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wl_subcompositor_destroy(wayland->toplevel->scompositor); - } else { - wl_subcompositor_destroy(wayland->sublevel->subcompositor); } } From 95dd0932f706cca1696942ebfeabfb80881a7aed Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 13 Sep 2026 01:40:40 -0700 Subject: [PATCH 056/168] fix? --- src/backend/wayland/interfaces.c | 33 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 73ac8b1..e0b962c 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -576,9 +576,9 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time inArea |= self->wayland.framebuffer.surface == curSurface; } - if(self->wayland.backbuffer.surface) { - inArea |= self->wayland.backbuffer.surface == curSurface; - } + // if(self->wayland.backbuffer.surface) { + // inArea |= self->wayland.backbuffer.surface == curSurface; + // } self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); @@ -601,7 +601,9 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time } MwLLWaylandCascadeChildren(self); } - + if(self->wayland.backbuffer.surface) { + wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); + } WAYLAND_EVENT_OP_END(self); }; @@ -663,7 +665,8 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { } } - point = topmost_parent->wayland.cur_mouse_pos; + point = topmost_parent->wayland.cur_mouse_pos; + relative_mouse_pos.x = point.x - absolute_pos.x; relative_mouse_pos.y = point.y - absolute_pos.y; @@ -721,9 +724,7 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri if(self->wayland.framebuffer.surface) { inArea |= self->wayland.framebuffer.surface == curSurface; } - if(self->wayland.backbuffer.surface) { - inArea |= self->wayland.backbuffer.surface == curSurface; - } + if(inArea) { switch(button) { case BTN_LEFT: @@ -737,29 +738,23 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri break; } self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; - // switch(state) { - // case WL_POINTER_BUTTON_STATE_PRESSED: - // MwLLDispatch(self, down, &p); - // break; - // case WL_POINTER_BUTTON_STATE_RELEASED: - // MwLLDispatch(self, up, &p); - // break; - // } for(i = 0; i < arrlen(self->wayland.currentlyHeldWidgets); i++) { arrdel(self->wayland.currentlyHeldWidgets, i); } mouse_dispatch(self, p, state); - + } + if(self->wayland.backbuffer.surface) { if(!self->wayland.has_decorations && self->wayland.do_csd) { if(state != WL_POINTER_BUTTON_STATE_RELEASED) xdg_borderless_step_mdown(self, p, serial); else xdg_borderless_step_mup(self, p, serial); } - - MwLLForceRender(self); } + + MwLLForceRender(self); + WAYLAND_EVENT_OP_END(self); }; From e11b8f19399787cc1d3d8be023c5b2a1d296d968 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 13 Sep 2026 02:11:40 -0700 Subject: [PATCH 057/168] keyboard fix --- src/backend/wayland/interfaces.c | 83 +++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 24 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index e0b962c..b200dd2 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -634,6 +634,36 @@ static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { } }; +static bool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos) { + MwLL topmost_parent = child; + MwPoint point; + MwPoint relative_mouse_pos; + MwPoint absolute_pos; + + absolute_pos.x = child->wayland.x; + absolute_pos.y = child->wayland.y; + while(topmost_parent->wayland.parent) { + topmost_parent = topmost_parent->wayland.parent; + if(topmost_parent) { + absolute_pos.x += topmost_parent->wayland.x; + absolute_pos.y += topmost_parent->wayland.y; + } + } + + point = topmost_parent->wayland.cur_mouse_pos; + + relative_mouse_pos.x = point.x - absolute_pos.x; + relative_mouse_pos.y = point.y - absolute_pos.y; + + *_topmost_parent = topmost_parent; + *_point = point; + *_relative_mouse_pos = relative_mouse_pos; + *_absolute_pos = absolute_pos; + + return point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && + point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh; +} + static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { switch(state) { case WL_POINTER_BUTTON_STATE_PRESSED: @@ -655,24 +685,7 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { MwPoint relative_mouse_pos; MwPoint absolute_pos; - absolute_pos.x = child->wayland.x; - absolute_pos.y = child->wayland.y; - while(topmost_parent->wayland.parent) { - topmost_parent = topmost_parent->wayland.parent; - if(topmost_parent) { - absolute_pos.x += topmost_parent->wayland.x; - absolute_pos.y += topmost_parent->wayland.y; - } - } - - point = topmost_parent->wayland.cur_mouse_pos; - - relative_mouse_pos.x = point.x - absolute_pos.x; - relative_mouse_pos.y = point.y - absolute_pos.y; - - if( - point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && - point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh) { + if(hit_detect(child, &topmost_parent, &point, &relative_mouse_pos, &absolute_pos)) { int idx = -1; for(n = 0; n < arrlen(topmost_parent->wayland.currentlyHeldWidgets); n++) { if(topmost_parent->wayland.currentlyHeldWidgets[n] == child) { @@ -844,6 +857,32 @@ static void keyboard_leave(void* data, WAYLAND_EVENT_OP_END(self); }; +static void key_dispatch(MwLL self, int* k, MwBool down) { + if(self->common.user) { + MwWidget w = self->common.user; + int i, n; + for(i = 0; i < arrlen(w->children); i++) { + if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { + MwLL child = w->children[i]->lowlevel; + MwLL topmost_parent = child; + MwPoint point; + MwPoint relative_mouse_pos; + MwPoint absolute_pos; + + if(hit_detect(child, &topmost_parent, &point, &relative_mouse_pos, &absolute_pos)) { + if(down) { + MwLLDispatch(child, key, k); + } else { + MwLLDispatch(child, key_released, k); + } + + key_dispatch(child, k, down); + } + } + } + } +} + /* `wl_keyboard.key` callback */ static void keyboard_key(void* data, struct wl_keyboard* wl_keyboard, @@ -867,13 +906,10 @@ static void keyboard_key(void* data, inArea |= self->wayland.framebuffer.surface == curSurface; } - if(self->wayland.backbuffer.surface) { - inArea |= self->wayland.backbuffer.surface == curSurface; - } - inArea |= (self == topmost_parent->wayland.focusedWidget); if(inArea) { + xkb_layout_index_t layout; MwU32 levels; xkb_level_index_t level = 0; @@ -957,13 +993,12 @@ static void keyboard_key(void* data, if(key != -1) { if(state == WL_KEYBOARD_KEY_STATE_PRESSED) { - recursive_dispatch_key(self, &key); self->wayland.holding_key = MwTRUE; self->wayland.last_pressed_key = key; } else { - recursive_dispatch_key_released(self, &key); self->wayland.holding_key = MwFALSE; } + key_dispatch(self, &key, state == WL_KEYBOARD_KEY_STATE_PRESSED); self->wayland.start_time = MwTimeGetTick(); self->wayland.next_elapsed = self->wayland.keyboard_delay; } From 8fb77771bb52511ccf53a1eb6ae5f094bd2e3c7c Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 13 Sep 2026 18:13:31 +0900 Subject: [PATCH 058/168] bool --- src/backend/wayland/interfaces.c | 1 + src/backend/wayland/wayland.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index b200dd2..0ab3f43 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -11,6 +11,7 @@ #include #endif +#include #include static void setup_clipboard(MwLL self, struct wl_seat* wl_seat); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 3c2d9bd..2b5fce9 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1984,7 +1984,7 @@ static int MwLLWaylandCallInitImpl(void) { #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { - loadWayland = 0; + loadWayland = 1; } #endif From c6aaf54656847a37ed2e996469bb5661636857b9 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 13 Sep 2026 20:11:01 +0900 Subject: [PATCH 059/168] add clock widget (closes #35) --- examples/basic/periodic.c | 9 +++ examples/basic/rotate.c | 2 +- examples/gldemos/gears.c | 2 +- include/Mw/Draw.h | 7 ++ include/Mw/MachDep.h | 2 +- include/Mw/Milsko.h | 1 + include/Mw/StringDefs.h | 3 + include/Mw/Widget/Clock.h | 24 +++++++ milsko.xml | 10 +++ pl/rules.pl | 4 +- src/abstract/charset.c | 4 +- src/core.c | 2 +- src/draw.c | 18 ++--- src/widget/chart.c | 0 src/widget/clock.c | 138 ++++++++++++++++++++++++++++++++++++++ 15 files changed, 210 insertions(+), 16 deletions(-) create mode 100644 include/Mw/Widget/Clock.h create mode 100644 src/widget/chart.c create mode 100644 src/widget/clock.c diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index b449f09..06a115b 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -245,6 +245,15 @@ int main() { MwNscale, 1, NULL); + f = frame("Clock", -PaddingContent, -PaddingContent, MwClockClass, + MwNhour, 15, + MwNminute, 0, + MwNsecond, 10, + NULL); + + f = frame("Chart", -PaddingContent, -PaddingContent, MwCalendarClass, + NULL); + f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL); w = child(f); MwComboBoxAdd(w, -1, "Hello!"); diff --git a/examples/basic/rotate.c b/examples/basic/rotate.c index dbf9c5e..112d5fc 100644 --- a/examples/basic/rotate.c +++ b/examples/basic/rotate.c @@ -4,7 +4,7 @@ #include #ifndef M_PI -#define M_PI 3.14159265 +#define M_PI 3.14159265359 #endif #define SIZE 100 diff --git a/examples/gldemos/gears.c b/examples/gldemos/gears.c index 5d06b06..a1aad90 100644 --- a/examples/gldemos/gears.c +++ b/examples/gldemos/gears.c @@ -13,7 +13,7 @@ #include #ifndef M_PI -#define M_PI 3.14159265 +#define M_PI 3.14159265359 #endif /** diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index 443835c..542aac5 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -13,6 +13,13 @@ extern "C" { #endif +/*! + * @brief Get a color difference for shadow + * @param handle Widget + * @return Color difference + */ +MWDECL int MWAPI MwGetColorDifference(MwWidget handle); + /*! * @brief Parses a color text * @param handle Widget diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 4c98b24..7313ce2 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -86,7 +86,7 @@ #endif #ifndef M_PI -#define M_PI 3.14159265 +#define M_PI 3.14159265359 #endif /* Windows */ diff --git a/include/Mw/Milsko.h b/include/Mw/Milsko.h index 9860990..7997bb6 100644 --- a/include/Mw/Milsko.h +++ b/include/Mw/Milsko.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 6ad4e46..39730db 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -54,6 +54,9 @@ #define MwNrowSpan "IrowSpan" #define MwNdisabled "Idisabled" #define MwNacceptsDnD "IacceptsDnD" +#define MwNhour "Ihour" +#define MwNminute "Iminute" +#define MwNsecond "Isecond" #define MwNtitle "Stitle" #define MwNtext "Stext" diff --git a/include/Mw/Widget/Clock.h b/include/Mw/Widget/Clock.h new file mode 100644 index 0000000..a8057fe --- /dev/null +++ b/include/Mw/Widget/Clock.h @@ -0,0 +1,24 @@ +/*! + * @file Mw/Widget/Clock.h + * @brief Clock widget + */ +#ifndef __MW_WIDGET_CLOCK_H__ +#define __MW_WIDGET_CLOCK_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @brief Clock widget class + */ +MWDECL MwClass MwClockClass; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/milsko.xml b/milsko.xml index a94c847..573b84d 100644 --- a/milsko.xml +++ b/milsko.xml @@ -106,6 +106,9 @@ + + + @@ -654,6 +657,13 @@ + + + + + + + diff --git a/pl/rules.pl b/pl/rules.pl index afc9ef9..220e550 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -66,7 +66,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); - scan_wayland_protocol("staging", "fifo", "-v1"); + scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); @@ -153,6 +153,8 @@ new_object("src/widget/box.c"); new_object("src/widget/button.c"); new_object("src/widget/calendar.c"); new_object("src/widget/checkbox.c"); +new_object("src/widget/chart.c"); +new_object("src/widget/clock.c"); new_object("src/widget/combobox.c"); new_object("src/widget/entry.c"); new_object("src/widget/frame.c"); diff --git a/src/abstract/charset.c b/src/abstract/charset.c index 2c339d5..4b831d5 100644 --- a/src/abstract/charset.c +++ b/src/abstract/charset.c @@ -2,8 +2,7 @@ char* MwACPTextToUTF8Text(const char* input) { #if defined(_WIN32) && defined(MW_HAS_WCHAR) - int mbbytes = (strlen(input) + 1) * 4; - int wbytes = 0; + int wbytes = 0; int len; wchar_t* wout; @@ -39,7 +38,6 @@ char* MwACPTextToUTF8Text(const char* input) { char* MwUTF8TextToACPText(const char* input) { #if defined(_WIN32) && defined(MW_HAS_WCHAR) int mbbytes = (strlen(input) + 1) * 4; - int wbytes = 0; int len; wchar_t* wout; diff --git a/src/core.c b/src/core.c index 3180922..2982c1e 100644 --- a/src/core.c +++ b/src/core.c @@ -5,7 +5,7 @@ #ifdef USE_COCOA #define PERIODIC #endif - +#define USE_CLASSIC_THEME #define RESIZE_ON_TICK #define DRAW(handle) \ diff --git a/src/draw.c b/src/draw.c index c7869e0..bbd0264 100644 --- a/src/draw.c +++ b/src/draw.c @@ -11,7 +11,7 @@ #include "../external/stb_ds.h" -static int get_color_diff(MwWidget handle) { +int MwGetColorDifference(MwWidget handle) { if(MwGetInteger(handle, MwNmodernLook)) { return 40; } else { @@ -121,7 +121,7 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { MwLLPixmap pixmap; int y; double darken = 0.; - int ColorDiff = get_color_diff(handle); + int ColorDiff = MwGetColorDifference(handle); double darkenStep = (ColorDiff / 2.) / rect->height; unsigned long sz = 1 * rect->height * 4; unsigned char* data = malloc(sz * 2); @@ -178,7 +178,7 @@ void MwDrawFrameWithBorder(MwWidget handle, MwRect* rect, MwLLColor color, int i if(MwGetInteger(handle, MwNmodernLook)) { MwDrawFrameEx(handle, rect, color, invert, border, 0, 0); } else { - int diff = get_color_diff(handle) / 3 * 2; + int diff = MwGetColorDifference(handle) / 3 * 2; if(border >= 2) { int i; @@ -236,7 +236,7 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { MwPoint p[6]; int border = MwDefaultBorderWidth(handle); - int ColorDiff = get_color_diff(handle) + (MwGetInteger(handle, MwNmodernLook) ? 48 : 0); + int ColorDiff = MwGetColorDifference(handle) + (MwGetInteger(handle, MwNmodernLook) ? 48 : 0); MwLLColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); MwLLColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); MwLLColor col = invert ? MwLightenColor(handle, color, -8, -8, -8) : MwLightenColor(handle, color, 0, 0, 0); @@ -312,7 +312,7 @@ void MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor back double cx, cy, rx, ry; int border; int x, y; - int ColorDiff = (get_color_diff(handle)); + int ColorDiff = (MwGetColorDifference(handle)); MwLLColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); MwLLColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); MwLLColor base = MwLightenColor(handle, color, 0, 0, 0); @@ -385,6 +385,8 @@ void MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor back pout[2] = (MwU8)mixColor->common.blue; pout[3] = 255; + + MwLLFreeColor(mixColor); } } } @@ -402,7 +404,7 @@ void MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor back static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { MwPoint p[7]; - int ColorDiff = get_color_diff(handle); + int ColorDiff = MwGetColorDifference(handle); MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff); MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, ColorDiff - diff, ColorDiff - diff, ColorDiff - diff); color_set_disabled_if_disabled(handle, darker); @@ -499,7 +501,7 @@ static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighte } static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { - int ColorDiff = get_color_diff(handle); + int ColorDiff = MwGetColorDifference(handle); MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff); MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff); MwRect r = *rect; @@ -539,7 +541,7 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int direction) { MwPoint p1[4], p2[4], p3[4], p4[3]; const int border = MwGetInteger(handle, MwNmodernLook) ? 2 : MwDefaultBorderWidth(handle); - int ColorDiff = get_color_diff(handle); + int ColorDiff = MwGetColorDifference(handle); MwLLColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); MwLLColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); MwLLColor col = invert ? MwLightenColor(handle, color, -8, -8, -8) : MwLightenColor(handle, color, 0, 0, 0); diff --git a/src/widget/chart.c b/src/widget/chart.c new file mode 100644 index 0000000..e69de29 diff --git a/src/widget/clock.c b/src/widget/clock.c new file mode 100644 index 0000000..547464a --- /dev/null +++ b/src/widget/clock.c @@ -0,0 +1,138 @@ +#include + +static int wcreate(MwWidget handle) { + MwSetDefault(handle); + + MwSetInteger(handle, MwNhour, 0); + MwSetInteger(handle, MwNminute, 0); + MwSetInteger(handle, MwNsecond, 0); + return 0; +} + +static void hand(MwWidget handle, double x, double y, double width, double length, double angle, MwLLColor inside, MwLLColor border) { + double w = MwGetInteger(handle, MwNwidth); + double h = MwGetInteger(handle, MwNheight); + MwPoint p[5]; + int i; + double rad = (angle - 90) / 180 * M_PI; + double c = cos(rad); + double s = sin(rad); + double c2 = cos(rad - 0.5 * M_PI); + double s2 = sin(rad - 0.5 * M_PI); + double c3 = cos(rad - M_PI); + double s3 = sin(rad - M_PI); + + p[0].x = c2 * width / 2; + p[0].y = s2 * width / 2; + + p[1].x = c3 * width / 2 * 2; + p[1].y = s3 * width / 2 * 2; + + p[2].x = -c2 * width / 2; + p[2].y = -s2 * width / 2; + + p[3].x = c * length; + p[3].y = s * length; + + for(i = 0; i < 4; i++) { + p[i].x += w / 2 + x; + p[i].y += h / 2 + y; + } + + p[4] = p[0]; + + MwLLPolygon(handle->lowlevel, p, 4, inside); + MwLLLine(handle->lowlevel, &p[0], border); + MwLLLine(handle->lowlevel, &p[1], border); + MwLLLine(handle->lowlevel, &p[2], border); + MwLLLine(handle->lowlevel, &p[3], border); +} + +static void draw(MwWidget handle) { + int ColorDiff = MwGetColorDifference(handle); + int ShadowDist; + int BaseWidth; + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwLLColor shadow = MwLightenColor(handle, base, -ColorDiff, -ColorDiff, -ColorDiff); + MwLLColor inside = MwParseColor(handle, MwGetText(handle, MwNsubBackground)); + MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNsubForeground)); + MwRect r; + int i; + double w; + double fs = (MwGetInteger(handle, MwNsecond) % 60); + double fm = (MwGetInteger(handle, MwNminute) % 60) + (MwGetInteger(handle, MwNsecond) % 60) / 60.0; + double s = (double)(MwGetInteger(handle, MwNsecond) % 60) / 60 * 360; + double m = ((double)(MwGetInteger(handle, MwNminute) % 60) + fs / 60.0) / 60 * 360; + double h = ((double)(MwGetInteger(handle, MwNhour) % 12) + fm / 60.0) / 12 * 360; + + r.x = 0; + r.y = 0; + r.width = MwGetInteger(handle, MwNwidth); + r.height = MwGetInteger(handle, MwNheight); + MwDrawRect(handle, &r, base); + + w = r.width < r.height ? r.width : r.height; + + BaseWidth = w / 10; + ShadowDist = BaseWidth / 3; + + for(i = 0; i < 12; i++) { + MwPoint p[2]; + double rad = i * 30 / 180.0 * M_PI; + double c = cos(rad); + double s = sin(rad); + double x, y; + double l = w / 2 / 5; + + x = r.width / 2 + c * w / 2 - l * c; + y = r.height / 2 + s * w / 2 - l * s; + + p[0].x = x + l * c / (i % 3 ? 2 : 1); + p[0].y = y + l * s / (i % 3 ? 2 : 1); + + p[1].x = x; + p[1].y = y; + + MwLLLine(handle->lowlevel, p, border); + } + + hand(handle, ShadowDist, ShadowDist, BaseWidth, w / 2 * 2 / 3, h, shadow, shadow); + hand(handle, ShadowDist, ShadowDist, BaseWidth, w / 2, m, shadow, shadow); + hand(handle, ShadowDist, ShadowDist, BaseWidth / 4, w / 2, s, shadow, shadow); + + hand(handle, 0, 0, w / 10, w / 2 * 2 / 3, h, inside, border); + hand(handle, 0, 0, BaseWidth, w / 2, m, inside, border); + hand(handle, 0, 0, BaseWidth / 4, w / 2, s, inside, border); + + MwLLFreeColor(border); + MwLLFreeColor(inside); + MwLLFreeColor(shadow); + MwLLFreeColor(base); +} + +static void prop_change(MwWidget handle, const char* key) { + if(strcmp(key, MwNhour) == 0 || strcmp(key, MwNminute) == 0 || strcmp(key, MwNsecond) == 0) MwForceRender(handle); +} + +MwClassRec MwClockClassRec = { + wcreate, /* create */ + NULL, /* destroy */ + draw, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + NULL, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ + NULL, + NULL, + NULL}; +MwClass MwClockClass = &MwClockClassRec; From 827fd80ba01e2fc2384af33569460baecbc6dd2f Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 13 Sep 2026 20:11:21 +0900 Subject: [PATCH 060/168] oops --- src/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.c b/src/core.c index 2982c1e..21b16ea 100644 --- a/src/core.c +++ b/src/core.c @@ -5,7 +5,7 @@ #ifdef USE_COCOA #define PERIODIC #endif -#define USE_CLASSIC_THEME +//#define USE_CLASSIC_THEME #define RESIZE_ON_TICK #define DRAW(handle) \ From 2ae8f67b53465d677bd2439a0fc942b546bb3db7 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 13 Sep 2026 20:17:48 +0900 Subject: [PATCH 061/168] regenerate makefiles --- NTMakefile | 6 ++++-- WatMakefile | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/NTMakefile b/NTMakefile index 63a4a2c..2d41468 100644 --- a/NTMakefile +++ b/NTMakefile @@ -79,7 +79,9 @@ clean: del /f /q src\widget\box.obj del /f /q src\widget\button.obj del /f /q src\widget\calendar.obj + del /f /q src\widget\chart.obj del /f /q src\widget\checkbox.obj + del /f /q src\widget\clock.obj del /f /q src\widget\combobox.obj del /f /q src\widget\entry.obj del /f /q src\widget\frame.obj @@ -320,8 +322,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index 4533f3c..0b4f73a 100644 --- a/WatMakefile +++ b/WatMakefile @@ -78,7 +78,9 @@ clean: .SYMBOLIC %erase src/widget/box.obj %erase src/widget/button.obj %erase src/widget/calendar.obj + %erase src/widget/chart.obj %erase src/widget/checkbox.obj + %erase src/widget/clock.obj %erase src/widget/combobox.obj %erase src/widget/entry.obj %erase src/widget/frame.obj @@ -319,8 +321,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/checkbox.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -462,8 +464,12 @@ src/widget/button.obj: src/widget/button.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/button.c src/widget/calendar.obj: src/widget/calendar.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/calendar.c +src/widget/chart.obj: src/widget/chart.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/chart.c src/widget/checkbox.obj: src/widget/checkbox.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/checkbox.c +src/widget/clock.obj: src/widget/clock.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/clock.c src/widget/combobox.obj: src/widget/combobox.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/combobox.c src/widget/entry.obj: src/widget/entry.c From efd1d32801d17265b78bf8cafc76d19c42a54532 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 13 Sep 2026 22:10:40 +0900 Subject: [PATCH 062/168] fix gdi and add dummy chart --- examples/basic/periodic.c | 37 +++++++++++++++++++++------- include/Mw/Milsko.h | 1 + include/Mw/Widget/Chart.h | 24 +++++++++++++++++++ src/backend/gdi.c | 4 ++-- src/backend/wayland/wayland.c | 2 +- src/core.c | 2 +- src/widget/chart.c | 45 +++++++++++++++++++++++++++++++++++ 7 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 include/Mw/Widget/Chart.h diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index 06a115b..5b65265 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -7,6 +7,7 @@ #define PaddingContent 2 MwWidget window, menu, table; +MwWidget wcal, wclock; MwMenu e; static void MWAPI resize(MwWidget handle, void* user, void* call) { @@ -21,6 +22,24 @@ static void MWAPI resize(MwWidget handle, void* user, void* call) { NULL); } +static void MWAPI tick(MwWidget handle, void* user, void* call) { + time_t t = time(NULL); + struct tm tm = *localtime(&t); + + MwVaApply(wcal, + MwNyear, (int)tm.tm_year + 1900, + MwNmonth, (int)tm.tm_mon, + MwNdate, (int)tm.tm_mday, + MwNday, (int)tm.tm_wday, + NULL); + + MwVaApply(wclock, + MwNhour, (int)tm.tm_hour, + MwNminute, (int)tm.tm_min, + MwNsecond, (int)tm.tm_sec, + NULL); +} + static void MWAPI resize_content(MwWidget handle, void* user, void* call) { MwWidget* ws = MwGetChildren(handle); if(ws != NULL) { @@ -241,17 +260,15 @@ int main() { } } - f = frame("Calendar", -PaddingContent, -PaddingContent, MwCalendarClass, - MwNscale, 1, - NULL); + f = frame("Calendar", -PaddingContent, -PaddingContent, MwCalendarClass, + MwNscale, 1, + NULL); + wcal = child(f); - f = frame("Clock", -PaddingContent, -PaddingContent, MwClockClass, - MwNhour, 15, - MwNminute, 0, - MwNsecond, 10, - NULL); + f = frame("Clock", -PaddingContent, -PaddingContent, MwClockClass, NULL); + wclock = child(f); - f = frame("Chart", -PaddingContent, -PaddingContent, MwCalendarClass, + f = frame("Chart", -PaddingContent, -PaddingContent, MwChartClass, NULL); f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL); @@ -321,7 +338,9 @@ int main() { NULL); MwAddUserHandler(window, MwNresizeHandler, resize, NULL); + MwAddUserHandler(window, MwNtickHandler, tick, NULL); + tick(window, NULL, NULL); resize(window, NULL, NULL); MwVaApply(table, diff --git a/include/Mw/Milsko.h b/include/Mw/Milsko.h index 7997bb6..abdc073 100644 --- a/include/Mw/Milsko.h +++ b/include/Mw/Milsko.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Mw/Widget/Chart.h b/include/Mw/Widget/Chart.h new file mode 100644 index 0000000..6ab404b --- /dev/null +++ b/include/Mw/Widget/Chart.h @@ -0,0 +1,24 @@ +/*! + * @file Mw/Widget/Chart.h + * @brief Chart widget + */ +#ifndef __MW_WIDGET_CHART_H__ +#define __MW_WIDGET_CHART_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @brief Chart widget class + */ +MWDECL MwClass MwChartClass; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/backend/gdi.c b/src/backend/gdi.c index eace1d3..660a0fc 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -1000,11 +1000,11 @@ static void MwLLMakeToolWindowImpl(MwLL handle) { RECT rc; int w, h; + GetClientRect(handle->gdi.hWnd, &rc); + SetWindowLongPtr(handle->gdi.hWnd, GWL_STYLE, (LPARAM)lp); SetWindowLongPtr(handle->gdi.hWnd, GWL_EXSTYLE, (LPARAM)WS_EX_TOOLWINDOW); - GetClientRect(handle->gdi.hWnd, &rc); - w = rc.right - rc.left; h = rc.bottom - rc.top; diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 2b5fce9..3c2d9bd 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1984,7 +1984,7 @@ static int MwLLWaylandCallInitImpl(void) { #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { - loadWayland = 1; + loadWayland = 0; } #endif diff --git a/src/core.c b/src/core.c index 21b16ea..481fa34 100644 --- a/src/core.c +++ b/src/core.c @@ -5,7 +5,7 @@ #ifdef USE_COCOA #define PERIODIC #endif -//#define USE_CLASSIC_THEME +// #define USE_CLASSIC_THEME #define RESIZE_ON_TICK #define DRAW(handle) \ diff --git a/src/widget/chart.c b/src/widget/chart.c index e69de29..46f248e 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -0,0 +1,45 @@ +#include + +static int wcreate(MwWidget handle) { + return 0; +} + +static void draw(MwWidget handle) { + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwRect r; + + r.x = 0; + r.y = 0; + r.width = MwGetInteger(handle, MwNwidth); + r.height = MwGetInteger(handle, MwNheight); + MwDrawRect(handle, &r, base); + + MwLLFreeColor(base); +} + +static void prop_change(MwWidget handle, const char* key) { + if(strcmp(key, MwNhour) == 0 || strcmp(key, MwNminute) == 0 || strcmp(key, MwNsecond) == 0) MwForceRender(handle); +} + +MwClassRec MwChartClassRec = { + wcreate, /* create */ + NULL, /* destroy */ + draw, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + NULL, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ + NULL, + NULL, + NULL}; +MwClass MwChartClass = &MwChartClassRec; From 120eb5baaf5124243203b9a8f84481bd71a3eab2 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 01:09:57 +0900 Subject: [PATCH 063/168] bar chart --- examples/basic/periodic.c | 5 + include/Mw/Constants.h | 4 + include/Mw/Draw.h | 8 ++ include/Mw/StringDefs.h | 1 + include/Mw/TypeDefs.h | 12 +++ include/Mw/Widget/Chart.h | 33 ++++++ include/Mw/Widget/ComboBox.h | 17 +++ milsko.xml | 51 ++++++++- src/core.c | 2 +- src/draw.c | 61 +++++++++-- src/widget/chart.c | 203 +++++++++++++++++++++++++++++++---- src/widget/combobox.c | 50 ++++++--- src/widget/treeview.c | 1 + src/widget/window.c | 1 + 14 files changed, 405 insertions(+), 44 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index 5b65265..db833c6 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -270,6 +270,11 @@ int main() { f = frame("Chart", -PaddingContent, -PaddingContent, MwChartClass, NULL); + w = child(f); + MwChartAdd(w, -1, "A", -100, NULL); + MwChartAdd(w, -1, "B", 100, NULL); + MwChartAdd(w, -1, "C", 200, NULL); + MwChartAdd(w, -1, "D", 300, NULL); f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL); w = child(f); diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index 15853ff..ad29792 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -113,6 +113,10 @@ enum MwCLIPBOARD { MwCLIPBOARD_PRIMARY, }; +enum MwCHART { + MwCHART_BAR = 0 +}; + enum MwMOUSE { MwMOUSE_LEFT = 1, MwMOUSE_MIDDLE, diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index 542aac5..e3c6991 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -60,6 +60,14 @@ MWDECL MwLLColor MWAPI MwLightenColor(MwWidget handle, MwLLColor color, int r, i */ MWDECL void MWAPI MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color); +/*! + * @brief Draws a rectangle + * @param handle Widget + * @param rect Rectangle area + * @param color Color + */ +MWDECL void MWAPI MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color); + /*! * @brief Draws a filled rectangle that fades to a darker color * @param handle Widget diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 39730db..d820ea4 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -57,6 +57,7 @@ #define MwNhour "Ihour" #define MwNminute "Iminute" #define MwNsecond "Isecond" +#define MwNtype "Itype" #define MwNtitle "Stitle" #define MwNtext "Stext" diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index a9bc3cf..0be60e8 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -30,6 +30,8 @@ typedef struct _MwBox* MwBox; typedef struct _MwSubWindow* MwSubWindow; typedef struct _MwTab* MwTab; typedef struct _MwTable* MwTable; +typedef struct _MwChartEntry MwChartEntry; +typedef struct _MwChart* MwChart; typedef struct _MwMouse MwMouse; typedef struct _MwTTFInfo* MwTTFInfo; #ifdef _MILSKO @@ -247,6 +249,16 @@ struct _MwTab { char** names; }; +struct _MwChartEntry { + char* name; + char* color; + double value; +}; + +struct _MwChart { + MwChartEntry* entries; +}; + struct _MwMouse { MwPoint point; int button; diff --git a/include/Mw/Widget/Chart.h b/include/Mw/Widget/Chart.h index 6ab404b..d0957a2 100644 --- a/include/Mw/Widget/Chart.h +++ b/include/Mw/Widget/Chart.h @@ -17,6 +17,39 @@ extern "C" { */ MWDECL MwClass MwChartClass; +/*! + * @brief Adds the entry to the chart + * @param handle Widget + * @param index Index + * @param text Text + * @param value Value + * @return Index + */ +MwInline int MwChartAdd(MwWidget handle, int index, const char* text, double value, const char* color) { + int out; + + MwVaWidgetExecute(handle, "mwChartAdd", (void*)&out, index, text, value, color); + + return out; +} + +/*! + * @brief Deletes item from the chart + * @param handle Widget + * @param index Index + */ +MwInline void MwChartDelete(MwWidget handle, int index) { + MwVaWidgetExecute(handle, "mwChartDelete", NULL, index); +} + +/*! + * @brief Resets the chart + * @param handle Widget + */ +MwInline void MwChartReset(MwWidget handle) { + MwVaWidgetExecute(handle, "mwChartReset", NULL); +} + #ifdef __cplusplus } #endif diff --git a/include/Mw/Widget/ComboBox.h b/include/Mw/Widget/ComboBox.h index 7b2dc2f..fd5c343 100644 --- a/include/Mw/Widget/ComboBox.h +++ b/include/Mw/Widget/ComboBox.h @@ -41,6 +41,23 @@ MwInline const char* MwComboBoxGet(MwWidget handle, int index) { return text; } +/*! + * @brief Deletes the entry from combobox + * @param handle Widget + * @param index Index + */ +MwInline void MwComboBoxDelete(MwWidget handle, int index) { + MwVaWidgetExecute(handle, "mwComboBoxDelete", NULL, index); +} + +/*! + * @brief Resets the combobox + * @param handle Widget + */ +MwInline void MwComboBoxReset(MwWidget handle) { + MwVaWidgetExecute(handle, "mwComboBoxReset", NULL); +} + #ifdef __cplusplus } #endif diff --git a/milsko.xml b/milsko.xml index 573b84d..30efce1 100644 --- a/milsko.xml +++ b/milsko.xml @@ -1,10 +1,11 @@ @@ -228,6 +230,9 @@ 0 + + 0 + 1 @@ -649,6 +654,29 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -879,9 +907,26 @@ - - + + + + + + + + + + + + + + + + + + + diff --git a/src/core.c b/src/core.c index 481fa34..2982c1e 100644 --- a/src/core.c +++ b/src/core.c @@ -5,7 +5,7 @@ #ifdef USE_COCOA #define PERIODIC #endif -// #define USE_CLASSIC_THEME +#define USE_CLASSIC_THEME #define RESIZE_ON_TICK #define DRAW(handle) \ diff --git a/src/draw.c b/src/draw.c index bbd0264..5cbfd22 100644 --- a/src/draw.c +++ b/src/draw.c @@ -101,22 +101,67 @@ MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b) void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { MwPoint p[4]; + MwRect r = *rect; - p[0].x = rect->x; - p[0].y = rect->y; + if(r.width < 0) { + r.width *= -1; + r.x -= r.width; + } - p[1].x = rect->x + rect->width; - p[1].y = rect->y; + if(r.height < 0) { + r.height *= -1; + r.y -= r.height; + } - p[2].x = rect->x + rect->width; - p[2].y = rect->y + rect->height; + p[0].x = r.x; + p[0].y = r.y; - p[3].x = rect->x; - p[3].y = rect->y + rect->height; + p[1].x = r.x + r.width; + p[1].y = r.y; + + p[2].x = r.x + r.width; + p[2].y = r.y + r.height; + + p[3].x = r.x; + p[3].y = r.y + r.height; MwLLPolygon(handle->lowlevel, p, 4, color); } +void MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color) { + MwPoint p[5]; + MwRect r = *rect; + + if(r.width < 0) { + r.width *= -1; + r.x -= r.width; + } + + if(r.height < 0) { + r.height *= -1; + r.y -= r.height; + } + + p[0].x = r.x; + p[0].y = r.y; + + p[1].x = r.x + r.width; + p[1].y = r.y; + + p[2].x = r.x + r.width; + p[2].y = r.y + r.height; + + p[3].x = r.x; + p[3].y = r.y + r.height; + + p[4] = p[0]; + + MwLLLine(handle->lowlevel, &p[0], color); + MwLLLine(handle->lowlevel, &p[1], color); + MwLLLine(handle->lowlevel, &p[2], color); + MwLLLine(handle->lowlevel, &p[3], color); +} + void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { MwLLPixmap pixmap; int y; diff --git a/src/widget/chart.c b/src/widget/chart.c index 46f248e..b014513 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -1,12 +1,62 @@ #include +#include "../../external/stb_ds.h" + +static const char* palette0[] = { + "#800", + "#080", + "#880", + "#008", + "#808", + "#088", + "#888", + "#f00", + "#0f0", + "#ff0", + "#00f", + "#f0f", + "#0ff", + "#fff", + NULL}; + static int wcreate(MwWidget handle) { + MwChart c = malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + + handle->internal = c; + + MwSetDefault(handle); + return 0; } +static void destroy(MwWidget handle) { + MwChartReset(handle); + free(handle->internal); +} + static void draw(MwWidget handle) { - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwRect r; + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwRect r; + MwChart c = handle->internal; + int i; + const char** colors = palette0; + int n; + int gap; + int width; + MwRect node; + double min = 0xffffffff; + double max = -0xffffffff; + int space = MwTextHeight(handle, NULL, "M"); + MwPoint p[2]; + + for(n = 0; colors[n] != NULL; n++); + + for(i = 0; i < arrlen(c->entries); i++) { + if(min > c->entries[i].value) min = c->entries[i].value; + if(max < c->entries[i].value) max = c->entries[i].value; + } r.x = 0; r.y = 0; @@ -14,31 +64,144 @@ static void draw(MwWidget handle) { r.height = MwGetInteger(handle, MwNheight); MwDrawRect(handle, &r, base); + if(min > 0) { + min = 0; + } else if(min < 0) { + min -= r.height / 10; + } + + node.x = 16; + node.y = 0; + + width = (r.width - node.x) * 2 / (arrlen(c->entries) * 3 + 1); + gap = width / 2; + + p[0].x = node.x; + p[0].y = r.height - space; + + p[1].x = node.x + (width + gap) * arrlen(c->entries) + gap; + p[1].y = p[0].y; + MwLLLine(handle->lowlevel, &p[0], border); + + p[0].y = r.height - space - abs(min / (max - min) * (r.height - space)); + p[1].y = p[0].y; + MwLLLine(handle->lowlevel, &p[0], border); + MwDrawText(handle, NULL, p, "0", MwALIGNMENT_END, border); + + p[0].x = node.x; + p[0].y = 0; + + p[1].x = node.x; + p[1].y = r.height - space; + MwLLLine(handle->lowlevel, &p[0], border); + + node.width = width; + for(i = 0; i < arrlen(c->entries); i++) { + MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + + node.x += gap; + + node.height = c->entries[i].value / (max - min) * (r.height - space); + node.y = r.height - space - node.height - abs(min / (max - min) * (r.height - space)); + + MwDrawRect(handle, &node, color); + MwDrawRectLine(handle, &node, border); + + p[0].x = node.x + node.width / 2; + p[0].y = r.height - space / 2; + + MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); + + node.x += node.width; + + MwLLFreeColor(color); + } + + MwLLFreeColor(border); MwLLFreeColor(base); } static void prop_change(MwWidget handle, const char* key) { - if(strcmp(key, MwNhour) == 0 || strcmp(key, MwNminute) == 0 || strcmp(key, MwNsecond) == 0) MwForceRender(handle); + if(strcmp(key, MwNtype) == 0) MwForceRender(handle); +} + +static int mwChartAddImpl(MwWidget handle, int index, const char* text, double value, const char* color) { + MwChart c = handle->internal; + MwChartEntry e; + + if(index == -1) index = arrlen(c->entries); + + e.name = MwStringDuplicate(text); + e.color = color == NULL ? NULL : MwStringDuplicate(color); + e.value = value; + + arrins(c->entries, index, e); + + MwForceRender(handle); + + return index; +} + +static void mwChartDeleteImpl(MwWidget handle, int index) { + MwChart c = handle->internal; + + if(index == -1) index = arrlen(c->entries) - 1; + + free(c->entries[index].name); + if(c->entries[index].color != NULL) free(c->entries[index].color); + arrdel(c->entries, index); + + MwForceRender(handle); +} + +static void mwChartResetImpl(MwWidget handle) { + MwChart c = handle->internal; + int i; + + for(i = 0; i < arrlen(c->entries); i++) { + free(c->entries[i].name); + if(c->entries[i].color != NULL) free(c->entries[i].color); + } + arrfree(c->entries); + + MwForceRender(handle); +} + +static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { + if(strcmp(name, "mwChartAdd") == 0) { + int index = va_arg(va, int); + const char* text = va_arg(va, const char*); + double value = va_arg(va, double); + const char* color = va_arg(va, const char*); + *(int*)out = mwChartAddImpl(handle, index, text, value, color); + } + if(strcmp(name, "mwChartDelete") == 0) { + int index = va_arg(va, int); + mwChartDeleteImpl(handle, index); + } + if(strcmp(name, "mwChartReset") == 0) { + mwChartResetImpl(handle); + } } MwClassRec MwChartClassRec = { - wcreate, /* create */ - NULL, /* destroy */ - draw, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - prop_change, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - NULL, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ + wcreate, /* create */ + destroy, /* destroy */ + draw, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler, /* execute */ + NULL, /* tick */ + MwForceRender, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ NULL, NULL, NULL}; diff --git a/src/widget/combobox.c b/src/widget/combobox.c index e53647d..5502a07 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -20,12 +20,8 @@ static int wcreate(MwWidget handle) { static void destroy(MwWidget handle) { MwComboBox cb = handle->internal; - int i; - for(i = 0; i < arrlen(cb->list); i++) { - free(cb->list[i]); - } - arrfree(cb->list); + MwComboBoxReset(handle); free(handle->internal); } @@ -145,6 +141,13 @@ static void prop_change(MwWidget handle, const char* prop) { } } +static void parent_resize(MwWidget handle) { + MwComboBox cb = handle->internal; + if(cb->opened) { + click(handle); + } +} + static void mwComboBoxAddImpl(MwWidget handle, int index, const char* text) { MwComboBox cb = handle->internal; char* t = MwStringDuplicate(text); @@ -153,7 +156,7 @@ static void mwComboBoxAddImpl(MwWidget handle, int index, const char* text) { arrins(cb->list, index, t); - if(index <= MwGetInteger(handle, MwNvalue)) MwForceRender(handle); + MwForceRender(handle); } static const char* mwComboBoxGetImpl(MwWidget handle, int index) { @@ -162,6 +165,29 @@ static const char* mwComboBoxGetImpl(MwWidget handle, int index) { return cb->list[index]; } +static void mwComboBoxDeleteImpl(MwWidget handle, int index) { + MwComboBox cb = handle->internal; + int n = MwGetInteger(handle, MwNvalue); + + free(cb->list[index]); + arrdel(cb->list, index); + + if(index < n && n > 0) { + MwSetInteger(handle, MwNvalue, n - 1); + } + + MwForceRender(handle); +} + +static void mwComboBoxResetImpl(MwWidget handle) { + MwComboBox cb = handle->internal; + + arrfree(cb->list); + MwSetInteger(handle, MwNvalue, 0); + + MwForceRender(handle); +} + static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { if(strcmp(name, "mwComboBoxAdd") == 0) { int index = va_arg(va, int); @@ -172,12 +198,12 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v int index = va_arg(va, int); *(const char**)out = mwComboBoxGetImpl(handle, index); } -} - -static void parent_resize(MwWidget handle) { - MwComboBox cb = handle->internal; - if(cb->opened) { - click(handle); + if(strcmp(name, "mwComboBoxDelete") == 0) { + int index = va_arg(va, int); + mwComboBoxDeleteImpl(handle, index); + } + if(strcmp(name, "mwComboBoxReset") == 0) { + mwComboBoxResetImpl(handle); } } diff --git a/src/widget/treeview.c b/src/widget/treeview.c index 3fba309..d07d355 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -317,6 +317,7 @@ static int wcreate(MwWidget handle) { } static void destroy(MwWidget handle) { + MwTreeViewReset(handle); free(handle->internal); } diff --git a/src/widget/window.c b/src/widget/window.c index 3d0afe2..9ea16a3 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -51,6 +51,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v mwWindowShouldCloseImpl(handle, out); } } + MwClassRec MwWindowClassRec = { wcreate, /* create */ NULL, /* destroy */ From d87569d7c00e0d422f1d35b43073892c266ca3ee Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 02:51:00 +0900 Subject: [PATCH 064/168] things --- examples/basic/periodic.c | 18 ++-- include/Mw/Constants.h | 3 +- include/Mw/Draw.h | 7 ++ milsko.xml | 3 + src/core.c | 2 +- src/draw.c | 32 +++--- src/widget/chart.c | 198 ++++++++++++++++++++++++++++++-------- 7 files changed, 196 insertions(+), 67 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index db833c6..e40994d 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -269,12 +269,17 @@ int main() { wclock = child(f); f = frame("Chart", -PaddingContent, -PaddingContent, MwChartClass, + MwNtype, MwCHART_3D_BAR, + MwNcolumnSpan, 2, NULL); w = child(f); - MwChartAdd(w, -1, "A", -100, NULL); - MwChartAdd(w, -1, "B", 100, NULL); - MwChartAdd(w, -1, "C", 200, NULL); - MwChartAdd(w, -1, "D", 300, NULL); + MwChartAdd(w, -1, "A", -400, NULL); + MwChartAdd(w, -1, "B", -200, NULL); + MwChartAdd(w, -1, "C", -100, NULL); + MwChartAdd(w, -1, "D", 100, NULL); + MwChartAdd(w, -1, "E", 200, NULL); + MwChartAdd(w, -1, "F", 400, NULL); + MwChartAdd(w, -1, "G", 800, NULL); f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL); w = child(f); @@ -288,6 +293,7 @@ int main() { f = frame("Label", -PaddingContent, -PaddingContent, MwLabelClass, MwNtext, "Epic text\nNewline can be used too!", + MwNcolumnSpan, 2, NULL); f = frame("ListBox", -PaddingContent, -PaddingContent, MwListBoxClass, @@ -321,9 +327,7 @@ int main() { MwNtitle, "Sub window 2", NULL); - f = frame("Tab", -PaddingContent, -PaddingContent, MwTabClass, - MwNcolumnSpan, 2, - NULL); + f = frame("Tab", -PaddingContent, -PaddingContent, MwTabClass, NULL); w = child(f); MwSetText(MwTabAdd(w, "ABC"), MwNbackground, "#f00"); MwSetText(MwTabAdd(w, "DEF"), MwNbackground, "#0f0"); diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index ad29792..6df447d 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -114,7 +114,8 @@ enum MwCLIPBOARD { }; enum MwCHART { - MwCHART_BAR = 0 + MwCHART_BAR = 0, + MwCHART_3D_BAR, }; enum MwMOUSE { diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index e3c6991..ad13c60 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -52,6 +52,13 @@ MWDECL void MWAPI MwColorTableInit(void); */ MWDECL MwLLColor MWAPI MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b); +/*! + * @brief Fix a rectangle + * @param handle Widget + * @param rect Rectangle area + */ +MWDECL void MWAPI MwFixRect(MwRect* rect); + /*! * @brief Draws a filled rectangle * @param handle Widget diff --git a/milsko.xml b/milsko.xml index 30efce1..6bf802b 100644 --- a/milsko.xml +++ b/milsko.xml @@ -232,6 +232,7 @@ 0 + 1 @@ -657,6 +658,8 @@ + + diff --git a/src/core.c b/src/core.c index 2982c1e..481fa34 100644 --- a/src/core.c +++ b/src/core.c @@ -5,7 +5,7 @@ #ifdef USE_COCOA #define PERIODIC #endif -#define USE_CLASSIC_THEME +// #define USE_CLASSIC_THEME #define RESIZE_ON_TICK #define DRAW(handle) \ diff --git a/src/draw.c b/src/draw.c index 5cbfd22..eb15c76 100644 --- a/src/draw.c +++ b/src/draw.c @@ -99,19 +99,23 @@ MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b) return MwLLAllocColor(handle->lowlevel, cr, cg, cb); } +void MwFixRect(MwRect* rect) { + if(rect->width < 0) { + rect->width *= -1; + rect->x -= rect->width; + } + + if(rect->height < 0) { + rect->height *= -1; + rect->y -= rect->height; + } +} + void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { MwPoint p[4]; MwRect r = *rect; - if(r.width < 0) { - r.width *= -1; - r.x -= r.width; - } - - if(r.height < 0) { - r.height *= -1; - r.y -= r.height; - } + MwFixRect(&r); p[0].x = r.x; p[0].y = r.y; @@ -132,15 +136,7 @@ void MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color) { MwPoint p[5]; MwRect r = *rect; - if(r.width < 0) { - r.width *= -1; - r.x -= r.width; - } - - if(r.height < 0) { - r.height *= -1; - r.y -= r.height; - } + MwFixRect(&r); p[0].x = r.x; p[0].y = r.y; diff --git a/src/widget/chart.c b/src/widget/chart.c index b014513..34d8f4e 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -27,6 +27,8 @@ static int wcreate(MwWidget handle) { MwSetDefault(handle); + MwSetInteger(handle, MwNtype, MwCHART_BAR); + return 0; } @@ -35,6 +37,35 @@ static void destroy(MwWidget handle) { free(handle->internal); } +static void draw_line(MwWidget handle, const char* text, double x, double y, double width, double height, MwLLColor color) { + MwPoint p[2]; + int type = MwGetInteger(handle, MwNtype); + + p[0].x = x; + p[0].y = y; + + p[1].x = x + width; + p[1].y = p[0].y; + MwDrawText(handle, NULL, p, text, MwALIGNMENT_END, color); + + if(type == MwCHART_3D_BAR) { + MwPoint p2[2]; + + p2[0] = p[0]; + p2[1] = p[0]; + + p2[1].x += height; + p2[1].y -= height; + + MwLLLine(handle->lowlevel, &p2[0], color); + + p[0].x += height; + p[0].y -= height; + p[1].y -= height; + } + MwLLLine(handle->lowlevel, &p[0], color); +} + static void draw(MwWidget handle) { MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNforeground)); @@ -46,75 +77,162 @@ static void draw(MwWidget handle) { int gap; int width; MwRect node; - double min = 0xffffffff; - double max = -0xffffffff; + double vmin = 0xffffffff; + double vmax = -0xffffffff; int space = MwTextHeight(handle, NULL, "M"); MwPoint p[2]; + int type = MwGetInteger(handle, MwNtype); for(n = 0; colors[n] != NULL; n++); for(i = 0; i < arrlen(c->entries); i++) { - if(min > c->entries[i].value) min = c->entries[i].value; - if(max < c->entries[i].value) max = c->entries[i].value; + if(vmin > c->entries[i].value) vmin = c->entries[i].value; + if(vmax < c->entries[i].value) vmax = c->entries[i].value; } + if(MwGetInteger(handle, MwNminValue) != MwDEFAULT) vmin = MwGetInteger(handle, MwNminValue); + if(MwGetInteger(handle, MwNmaxValue) != MwDEFAULT) vmax = MwGetInteger(handle, MwNmaxValue); + r.x = 0; r.y = 0; r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); MwDrawRect(handle, &r, base); - if(min > 0) { - min = 0; - } else if(min < 0) { - min -= r.height / 10; - } + if(type == MwCHART_BAR || type == MwCHART_3D_BAR) { + double s = 1.5; + double ovmin = vmin; + double ovmax = vmax; + double twidth; + char buf[128]; - node.x = 16; - node.y = 0; + node.x = 128; + node.y = 0; - width = (r.width - node.x) * 2 / (arrlen(c->entries) * 3 + 1); - gap = width / 2; + width = (r.width - node.x) * s / (arrlen(c->entries) * (1 + s) + 1); + gap = width / s; - p[0].x = node.x; - p[0].y = r.height - space; + twidth = (width + gap) * arrlen(c->entries) + gap; - p[1].x = node.x + (width + gap) * arrlen(c->entries) + gap; - p[1].y = p[0].y; - MwLLLine(handle->lowlevel, &p[0], border); + if(vmin > 0) { + vmin = 0; + } else if(vmin < 0) { + vmin -= (double)width / r.height * (vmax - vmin); + } - p[0].y = r.height - space - abs(min / (max - min) * (r.height - space)); - p[1].y = p[0].y; - MwLLLine(handle->lowlevel, &p[0], border); - MwDrawText(handle, NULL, p, "0", MwALIGNMENT_END, border); + if(vmax < 0) { + vmax = 0; + } else if(vmax > 0) { + vmax += (double)width / r.height * (vmax - vmin); + } - p[0].x = node.x; - p[0].y = 0; + sprintf(buf, "%.2f", ovmax); + draw_line(handle, buf, node.x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - p[1].x = node.x; - p[1].y = r.height - space; - MwLLLine(handle->lowlevel, &p[0], border); + draw_line(handle, "0", node.x, (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - node.width = width; - for(i = 0; i < arrlen(c->entries); i++) { - MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + sprintf(buf, "%.2f", ovmin); + draw_line(handle, buf, node.x, (r.height - space) - (ovmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - node.x += gap; + p[0].x = node.x; + p[0].y = 0; - node.height = c->entries[i].value / (max - min) * (r.height - space); - node.y = r.height - space - node.height - abs(min / (max - min) * (r.height - space)); + p[1].x = node.x; + p[1].y = r.height - space; + MwLLLine(handle->lowlevel, &p[0], border); - MwDrawRect(handle, &node, color); - MwDrawRectLine(handle, &node, border); + p[0].x = node.x; + p[0].y = r.height - space; - p[0].x = node.x + node.width / 2; - p[0].y = r.height - space / 2; + p[1].x = node.x + twidth; + p[1].y = p[0].y; + MwLLLine(handle->lowlevel, &p[0], border); - MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); + node.width = width; + for(i = 0; i < arrlen(c->entries); i++) { + int ColorDiff = MwGetColorDifference(handle); + MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + MwLLColor colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); + MwLLColor colord = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); + MwPoint persp_top[5]; + MwPoint persp_right[5]; - node.x += node.width; + node.x += gap; - MwLLFreeColor(color); + node.height = -c->entries[i].value / (vmax - vmin) * (r.height - space); + node.y = (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space); + + MwDrawRect(handle, &node, color); + + if(type == MwCHART_3D_BAR) { + MwRect node2 = node; + + MwFixRect(&node2); + + persp_top[0] = *(MwPoint*)&node2; + persp_top[1] = *(MwPoint*)&node2; + persp_top[1].x += node2.width; + + persp_top[2] = persp_top[1]; + persp_top[3] = persp_top[0]; + + persp_top[2].x += node2.width / 2; + persp_top[2].y -= node2.width / 2; + + persp_top[3].x += node2.width / 2; + persp_top[3].y -= node2.width / 2; + + persp_top[4] = persp_top[0]; + + MwLLPolygon(handle->lowlevel, persp_top, 4, colorl); + + persp_right[0] = *(MwPoint*)&node2; + persp_right[1] = *(MwPoint*)&node2; + persp_right[0].x += node2.width; + persp_right[1].x += node2.width; + persp_right[1].y += node2.height; + + persp_right[2] = persp_right[1]; + persp_right[3] = persp_right[0]; + + persp_right[2].x += node2.width / 2; + persp_right[2].y -= node2.width / 2; + + persp_right[3].x += node2.width / 2; + persp_right[3].y -= node2.width / 2; + + persp_right[4] = persp_right[0]; + + MwLLPolygon(handle->lowlevel, persp_right, 4, colord); + } + + if(!MwGetInteger(handle, MwNmodernLook)) { + MwDrawRectLine(handle, &node, border); + + if(type == MwCHART_3D_BAR) { + MwLLLine(handle->lowlevel, &persp_top[0], border); + MwLLLine(handle->lowlevel, &persp_top[1], border); + MwLLLine(handle->lowlevel, &persp_top[2], border); + MwLLLine(handle->lowlevel, &persp_top[3], border); + + MwLLLine(handle->lowlevel, &persp_right[0], border); + MwLLLine(handle->lowlevel, &persp_right[1], border); + MwLLLine(handle->lowlevel, &persp_right[2], border); + MwLLLine(handle->lowlevel, &persp_right[3], border); + } + } + + p[0].x = node.x + node.width / 2; + p[0].y = r.height - space / 2; + + MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); + + node.x += node.width; + + MwLLFreeColor(colord); + MwLLFreeColor(colorl); + MwLLFreeColor(color); + } } MwLLFreeColor(border); From 51aaf52422d89440cb58987adb83863777b4c0da Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 02:55:14 +0900 Subject: [PATCH 065/168] fix --- src/widget/chart.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/widget/chart.c b/src/widget/chart.c index 34d8f4e..cec1c9a 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -10,13 +10,6 @@ static const char* palette0[] = { "#808", "#088", "#888", - "#f00", - "#0f0", - "#ff0", - "#00f", - "#f0f", - "#0ff", - "#fff", NULL}; static int wcreate(MwWidget handle) { From b86fe4f306a1455ca6ff24899d5ff8c8b3008ba9 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 02:59:35 +0900 Subject: [PATCH 066/168] fix --- src/widget/chart.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/widget/chart.c b/src/widget/chart.c index cec1c9a..83e3a5e 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -12,6 +12,8 @@ static const char* palette0[] = { "#888", NULL}; +#define NUMFMT "%.2f" + static int wcreate(MwWidget handle) { MwChart c = malloc(sizeof(*c)); memset(c, 0, sizeof(*c)); @@ -99,7 +101,18 @@ static void draw(MwWidget handle) { double twidth; char buf[128]; - node.x = 128; + node.x = 0; + + for(i = 0; i < arrlen(c->entries); i++) { + int w; + + sprintf(buf, NUMFMT, c->entries[i].value); + + w = MwTextWidth(handle, NULL, buf); + + if(node.x < w) node.x = w; + } + node.y = 0; width = (r.width - node.x) * s / (arrlen(c->entries) * (1 + s) + 1); @@ -119,12 +132,12 @@ static void draw(MwWidget handle) { vmax += (double)width / r.height * (vmax - vmin); } - sprintf(buf, "%.2f", ovmax); + sprintf(buf, NUMFMT, ovmax); draw_line(handle, buf, node.x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); draw_line(handle, "0", node.x, (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - sprintf(buf, "%.2f", ovmin); + sprintf(buf, NUMFMT, ovmin); draw_line(handle, buf, node.x, (r.height - space) - (ovmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); p[0].x = node.x; From 95a7db7f5449f753e7919d1775c818d833f09df1 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 03:07:25 +0900 Subject: [PATCH 067/168] ok --- examples/basic/periodic.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index e40994d..c17cfd0 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -273,13 +273,14 @@ int main() { MwNcolumnSpan, 2, NULL); w = child(f); - MwChartAdd(w, -1, "A", -400, NULL); - MwChartAdd(w, -1, "B", -200, NULL); - MwChartAdd(w, -1, "C", -100, NULL); - MwChartAdd(w, -1, "D", 100, NULL); - MwChartAdd(w, -1, "E", 200, NULL); - MwChartAdd(w, -1, "F", 400, NULL); - MwChartAdd(w, -1, "G", 800, NULL); + MwChartAdd(w, -1, "A", -800, NULL); + MwChartAdd(w, -1, "B", -400, NULL); + MwChartAdd(w, -1, "C", -200, NULL); + MwChartAdd(w, -1, "D", -100, NULL); + MwChartAdd(w, -1, "E", 100, NULL); + MwChartAdd(w, -1, "F", 200, NULL); + MwChartAdd(w, -1, "G", 400, NULL); + MwChartAdd(w, -1, "H", 800, NULL); f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL); w = child(f); From 3ac6b8387cf0e18e7215736a0f9ed7f0ef98bcce Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 03:37:00 +0900 Subject: [PATCH 068/168] change font size --- resource/font/{7x14.bdf => 7x13.bdf} | 5122 ++++++++++++------------ resource/font/{7x14B.bdf => 7x13B.bdf} | 4991 ++++++++++++----------- src/default.c | 20 + src/text/font/boldfont.c | 512 +-- src/text/font/font.c | 514 +-- src/text/text.c | 4 +- 6 files changed, 5694 insertions(+), 5469 deletions(-) rename resource/font/{7x14.bdf => 7x13.bdf} (54%) rename resource/font/{7x14B.bdf => 7x13B.bdf} (53%) diff --git a/resource/font/7x14.bdf b/resource/font/7x13.bdf similarity index 54% rename from resource/font/7x14.bdf rename to resource/font/7x13.bdf index 6e6c13e..c701341 100644 --- a/resource/font/7x14.bdf +++ b/resource/font/7x13.bdf @@ -1,12 +1,27 @@ STARTFONT 2.1 -COMMENT -COMMENT Donated by H. Kagotani ; public domain -COMMENT font from Japan -COMMENT -FONT -Misc-Fixed-Medium-R-Normal--14-130-75-75-C-70-ISO8859-1 -SIZE 7 75 75 -FONTBOUNDINGBOX 7 14 0 -2 -STARTPROPERTIES 19 +COMMENT $XConsortium: 7x13.bdf,v 1.11 92/04/02 14:25:38 gildea Exp $ +COMMENT +COMMENT Copyright (c) 1990 Stephen Gildea +COMMENT +COMMENT Permission to use, copy, modify, and distribute this software for +COMMENT any purpose is hereby granted without fee, provided that the above +COMMENT copyright notice and this permission notice appear in all copies. +COMMENT The authors make no representations about the suitability of this +COMMENT software for any purpose. It is provided "as is" without express +COMMENT or implied warranty. +COMMENT +COMMENT Designed by Stephen Gildea +COMMENT Original design November 1989. +COMMENT Current version June 1990. +COMMENT +COMMENT Characters above 127 designed and made by +COMMENT Thomas Bagli (pyramid!pcsbst!tom@uunet.UU.NET) +COMMENT PCS Computer Systeme, West Germany +COMMENT +FONT -Misc-Fixed-Medium-R-Normal--13-120-75-75-C-70-ISO8859-1 +SIZE 13 78 78 +FONTBOUNDINGBOX 7 13 0 -2 +STARTPROPERTIES 21 FONTNAME_REGISTRY "" FOUNDRY "Misc" FAMILY_NAME "Fixed" @@ -14,67 +29,247 @@ WEIGHT_NAME "Medium" SLANT "R" SETWIDTH_NAME "Normal" ADD_STYLE_NAME "" -PIXEL_SIZE 14 -POINT_SIZE 130 +PIXEL_SIZE 13 +POINT_SIZE 120 RESOLUTION_X 75 RESOLUTION_Y 75 SPACING "C" AVERAGE_WIDTH 70 CHARSET_REGISTRY "ISO8859" CHARSET_ENCODING "1" -DEFAULT_CHAR 32 +UNDERLINE_POSITION -1 +DESTINATION 1 +DEFAULT_CHAR 0 FONT_DESCENT 2 -FONT_ASCENT 12 -COPYRIGHT "Public domain font. Share and enjoy." +FONT_ASCENT 11 +DATE "June 1990" ENDPROPERTIES -CHARS 209 -STARTCHAR 0001 +CHARS 224 +STARTCHAR Error +ENCODING 0 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +78 +78 +78 +78 +78 +78 +78 +78 +78 +78 +78 +00 +ENDCHAR +STARTCHAR C001 ENCODING 1 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -18 -3C -3C -7E -7E -3C -3C -18 -18 +00 +00 +00 +20 +70 +f8 +70 +20 +00 00 00 ENDCHAR -STARTCHAR 0002 +STARTCHAR C002 ENCODING 2 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP +00 +a8 54 -AA +a8 54 -AA +a8 54 -AA +a8 54 -AA +a8 54 -AA +a8 54 -AA -54 -AA ENDCHAR -STARTCHAR 000b +STARTCHAR HT +ENCODING 3 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +90 +90 +f0 +90 +90 +1c +08 +08 +08 +08 +00 +ENDCHAR +STARTCHAR FF +ENCODING 4 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +f0 +80 +e0 +80 +80 +3c +20 +38 +20 +20 +00 +ENDCHAR +STARTCHAR CR +ENCODING 5 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +70 +80 +80 +80 +70 +38 +24 +38 +28 +24 +00 +ENDCHAR +STARTCHAR LF +ENCODING 6 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +80 +80 +80 +80 +f0 +3c +20 +38 +20 +20 +00 +ENDCHAR +STARTCHAR Degree +ENCODING 7 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +70 +88 +88 +70 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR Plus/Minus +ENCODING 8 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +20 +20 +f8 +20 +20 +00 +f8 +00 +00 +00 +ENDCHAR +STARTCHAR NL +ENCODING 9 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +90 +d0 +b0 +90 +90 +20 +20 +20 +20 +3c +00 +ENDCHAR +STARTCHAR VT +ENCODING 10 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +88 +88 +50 +50 +20 +7c +10 +10 +10 +10 +00 +ENDCHAR +STARTCHAR C013 ENCODING 11 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 10 10 @@ -82,8 +277,7 @@ BITMAP 10 10 10 -10 -F0 +f0 00 00 00 @@ -91,11 +285,11 @@ F0 00 00 ENDCHAR -STARTCHAR 000c +STARTCHAR C014 ENCODING 12 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -103,8 +297,7 @@ BITMAP 00 00 00 -00 -F0 +f0 10 10 10 @@ -112,11 +305,11 @@ F0 10 10 ENDCHAR -STARTCHAR 000d +STARTCHAR C015 ENCODING 13 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -124,8 +317,7 @@ BITMAP 00 00 00 -00 -1E +1e 10 10 10 @@ -133,11 +325,11 @@ BITMAP 10 10 ENDCHAR -STARTCHAR 000e +STARTCHAR C016 ENCODING 14 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 10 10 @@ -145,8 +337,7 @@ BITMAP 10 10 10 -10 -1E +1e 00 00 00 @@ -154,11 +345,11 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 000f +STARTCHAR C017 ENCODING 15 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 10 10 @@ -166,8 +357,7 @@ BITMAP 10 10 10 -10 -FE +fe 10 10 10 @@ -175,16 +365,15 @@ FE 10 10 ENDCHAR -STARTCHAR 0010 +STARTCHAR C020 ENCODING 16 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -FE -00 00 00 +fe 00 00 00 @@ -196,18 +385,17 @@ FE 00 00 ENDCHAR -STARTCHAR 0011 +STARTCHAR C021 ENCODING 17 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 -FE -00 +fe 00 00 00 @@ -217,11 +405,11 @@ FE 00 00 ENDCHAR -STARTCHAR 0012 +STARTCHAR C022 ENCODING 18 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -229,8 +417,7 @@ BITMAP 00 00 00 -00 -FE +fe 00 00 00 @@ -238,11 +425,11 @@ FE 00 00 ENDCHAR -STARTCHAR 0013 +STARTCHAR C023 ENCODING 19 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -252,18 +439,17 @@ BITMAP 00 00 00 -00 -FE +fe 00 00 00 00 ENDCHAR -STARTCHAR 0014 +STARTCHAR C024 ENCODING 20 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -275,16 +461,15 @@ BITMAP 00 00 00 +fe 00 00 -00 -FE ENDCHAR -STARTCHAR 0015 +STARTCHAR C025 ENCODING 21 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 10 10 @@ -292,8 +477,7 @@ BITMAP 10 10 10 -10 -1E +1e 10 10 10 @@ -301,11 +485,11 @@ BITMAP 10 10 ENDCHAR -STARTCHAR 0016 +STARTCHAR C026 ENCODING 22 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 10 10 @@ -313,8 +497,7 @@ BITMAP 10 10 10 -10 -F0 +f0 10 10 10 @@ -322,11 +505,11 @@ F0 10 10 ENDCHAR -STARTCHAR 0017 +STARTCHAR C027 ENCODING 23 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 10 10 @@ -334,8 +517,7 @@ BITMAP 10 10 10 -10 -FE +fe 00 00 00 @@ -343,11 +525,11 @@ FE 00 00 ENDCHAR -STARTCHAR 0018 +STARTCHAR C030 ENCODING 24 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -355,8 +537,7 @@ BITMAP 00 00 00 -00 -FE +fe 10 10 10 @@ -364,11 +545,11 @@ FE 10 10 ENDCHAR -STARTCHAR 0019 +STARTCHAR C031 ENCODING 25 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 10 10 @@ -383,13 +564,132 @@ BITMAP 10 10 10 -10 ENDCHAR -STARTCHAR 0020 +STARTCHAR <= +ENCODING 26 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +04 +18 +60 +80 +60 +18 +04 +fc +00 +00 +ENDCHAR +STARTCHAR >= +ENCODING 27 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +80 +60 +18 +04 +18 +60 +80 +fc +00 +00 +ENDCHAR +STARTCHAR Pi +ENCODING 28 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +fc +48 +48 +48 +48 +88 +00 +00 +ENDCHAR +STARTCHAR Not Equal +ENCODING 29 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +04 +08 +fc +10 +20 +fc +40 +80 +00 +00 +ENDCHAR +STARTCHAR Pound Sterling +ENCODING 30 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +38 +44 +40 +40 +e0 +40 +40 +44 +b8 +00 +00 +ENDCHAR +STARTCHAR Cdot +ENCODING 31 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR Space ENCODING 32 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -404,13 +704,12 @@ BITMAP 00 00 00 -00 ENDCHAR -STARTCHAR 0021 +STARTCHAR ! ENCODING 33 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -423,22 +722,20 @@ BITMAP 10 00 10 -10 00 00 ENDCHAR -STARTCHAR 0022 +STARTCHAR " ENCODING 34 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -6C -24 -24 -48 00 00 +28 +28 +28 00 00 00 @@ -448,102 +745,97 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 0023 +STARTCHAR # ENCODING 35 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -0A -0A -0A -7E -14 -14 -7E +00 28 28 +7c 28 +7c +28 +28 +00 00 00 ENDCHAR -STARTCHAR 0024 +STARTCHAR $ ENCODING 36 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -08 -3C -4A -4A -28 -1C -0A -4A -4A -3C -08 +00 +10 +3c +50 +38 +14 +78 +10 +00 +00 00 ENDCHAR -STARTCHAR 0025 +STARTCHAR % ENCODING 37 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -32 -4A -4C -38 -08 +44 +a4 +48 10 -1C -32 -52 -4C +10 +20 +48 +94 +88 00 00 ENDCHAR -STARTCHAR 0026 +STARTCHAR & ENCODING 38 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -24 -24 -24 -18 -32 -4A -44 -4C -32 +00 +00 +60 +90 +90 +60 +94 +88 +74 00 00 ENDCHAR -STARTCHAR 0027 +STARTCHAR ' ENCODING 39 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP +00 +00 +38 30 -10 -10 -20 -00 -00 +40 00 00 00 @@ -553,74 +845,71 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 0028 +STARTCHAR ( ENCODING 40 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -02 -04 -08 +00 08 10 10 -10 +20 +20 +20 10 10 08 -08 -04 -02 +00 +00 ENDCHAR -STARTCHAR 0029 +STARTCHAR ) ENCODING 41 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -40 +00 20 10 10 08 08 08 -08 -08 10 10 20 -40 +00 +00 ENDCHAR -STARTCHAR 002a +STARTCHAR * ENCODING 42 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 -08 -2A -1C -08 -08 -1C -2A -08 +00 +48 +30 +fc +30 +48 +00 00 00 00 ENDCHAR -STARTCHAR 002b +STARTCHAR + ENCODING 43 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -628,20 +917,19 @@ BITMAP 00 10 10 -10 -7C -10 +7c 10 10 00 00 00 +00 ENDCHAR -STARTCHAR 002c +STARTCHAR , ENCODING 44 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -652,17 +940,16 @@ BITMAP 00 00 00 -00 +38 30 -10 -10 -20 +40 +00 ENDCHAR -STARTCHAR 002d +STARTCHAR - ENCODING 45 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -670,8 +957,7 @@ BITMAP 00 00 00 -00 -7E +fc 00 00 00 @@ -679,11 +965,11 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 002e +STARTCHAR . ENCODING 46 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -694,294 +980,279 @@ BITMAP 00 00 00 -00 10 +38 10 00 -00 ENDCHAR -STARTCHAR 002f +STARTCHAR / ENCODING 47 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -02 -02 +00 04 04 08 08 -08 -10 10 20 20 40 40 +00 +00 ENDCHAR -STARTCHAR 0030 +STARTCHAR 0 ENCODING 48 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -24 -42 -42 -42 -42 -42 -42 -24 -18 +30 +48 +84 +84 +84 +84 +84 +48 +30 00 00 ENDCHAR -STARTCHAR 0031 +STARTCHAR 1 ENCODING 49 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -08 -18 -28 -08 -08 -08 -08 -08 -08 -3E +10 +30 +50 +10 +10 +10 +10 +10 +7c 00 00 ENDCHAR -STARTCHAR 0032 +STARTCHAR 2 ENCODING 50 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -02 -04 +78 +84 +84 04 08 -10 -20 -7E +30 +40 +80 +fc 00 00 ENDCHAR -STARTCHAR 0033 +STARTCHAR 3 ENCODING 51 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -02 -1C -02 -02 -42 -42 -3C +fc +04 +08 +10 +38 +04 +04 +84 +78 00 00 ENDCHAR -STARTCHAR 0034 +STARTCHAR 4 ENCODING 52 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -04 -0C -14 -14 -24 -24 -44 -7E -04 -04 +08 +18 +28 +48 +88 +88 +fc +08 +08 00 00 ENDCHAR -STARTCHAR 0035 +STARTCHAR 5 ENCODING 53 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7E -40 -40 -7C -42 -02 -02 -42 -42 -3C +fc +80 +80 +b8 +c4 +04 +04 +84 +78 00 00 ENDCHAR -STARTCHAR 0036 +STARTCHAR 6 ENCODING 54 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -1C -22 -42 +38 40 -5C -62 -42 -42 -42 -3C +80 +80 +b8 +c4 +84 +84 +78 00 00 ENDCHAR -STARTCHAR 0037 +STARTCHAR 7 ENCODING 55 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7E -42 -44 +fc 04 08 -08 -08 -08 -08 -08 +10 +10 +20 +20 +40 +40 00 00 ENDCHAR -STARTCHAR 0038 +STARTCHAR 8 ENCODING 56 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -24 -18 -24 -42 -42 -42 -3C +78 +84 +84 +84 +78 +84 +84 +84 +78 00 00 ENDCHAR -STARTCHAR 0039 +STARTCHAR 9 ENCODING 57 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -42 -46 -3A -02 -42 -44 -38 +78 +84 +84 +8c +74 +04 +04 +08 +70 00 00 ENDCHAR -STARTCHAR 003a +STARTCHAR : ENCODING 58 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 10 +38 10 00 00 -00 10 +38 10 00 -00 -00 ENDCHAR -STARTCHAR 003b +STARTCHAR ; ENCODING 59 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 10 +38 10 00 00 -00 +38 30 -10 -10 -20 +40 00 ENDCHAR -STARTCHAR 003c +STARTCHAR < ENCODING 60 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -00 04 08 10 @@ -994,36 +1265,34 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 003d +STARTCHAR = ENCODING 61 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -7E +fc 00 00 -7E -00 +fc 00 00 00 00 ENDCHAR -STARTCHAR 003e +STARTCHAR > ENCODING 62 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -00 40 20 10 @@ -1036,1342 +1305,1278 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 003f +STARTCHAR ? ENCODING 63 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 +78 +84 +84 04 08 -08 -08 +10 +10 00 -08 -08 +10 00 00 ENDCHAR -STARTCHAR 0040 +STARTCHAR @ ENCODING 64 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -1C -22 -4E -52 -52 -52 -52 -4E -20 -1E +78 +84 +84 +9c +a4 +ac +94 +80 +78 00 00 ENDCHAR -STARTCHAR 0041 +STARTCHAR A ENCODING 65 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -10 -18 -28 -24 -44 -42 -7E -42 -42 -42 +30 +48 +84 +84 +84 +fc +84 +84 +84 00 00 ENDCHAR -STARTCHAR 0042 +STARTCHAR B ENCODING 66 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7C -42 -42 +f8 44 -7C -42 -42 -42 -42 -7C +44 +44 +78 +44 +44 +44 +f8 00 00 ENDCHAR -STARTCHAR 0043 +STARTCHAR C ENCODING 67 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -40 -40 -40 -40 -42 -42 -3C +78 +84 +80 +80 +80 +80 +80 +84 +78 00 00 ENDCHAR -STARTCHAR 0044 +STARTCHAR D ENCODING 68 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -78 +f8 44 -42 -42 -42 -42 -42 -42 44 -78 +44 +44 +44 +44 +44 +f8 00 00 ENDCHAR -STARTCHAR 0045 +STARTCHAR E ENCODING 69 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7E -40 -40 -40 -7C -40 -40 -40 -40 -7E +fc +80 +80 +80 +f0 +80 +80 +80 +fc 00 00 ENDCHAR -STARTCHAR 0046 +STARTCHAR F ENCODING 70 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7E -40 -40 -40 -7C -40 -40 -40 -40 -40 +fc +80 +80 +80 +f0 +80 +80 +80 +80 00 00 ENDCHAR -STARTCHAR 0047 +STARTCHAR G ENCODING 71 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -40 -40 -4E -42 -42 -42 -3C +78 +84 +80 +80 +80 +9c +84 +8c +74 00 00 ENDCHAR -STARTCHAR 0048 +STARTCHAR H ENCODING 72 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -42 -42 -42 -42 -7E -42 -42 -42 -42 -42 +84 +84 +84 +84 +fc +84 +84 +84 +84 00 00 ENDCHAR -STARTCHAR 0049 +STARTCHAR I ENCODING 73 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3E -08 -08 -08 -08 -08 -08 -08 -08 -3E +f8 +20 +20 +20 +20 +20 +20 +20 +f8 00 00 ENDCHAR -STARTCHAR 004a +STARTCHAR J ENCODING 74 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -02 -02 -02 -02 -02 -02 -02 -42 -44 -38 +1c +08 +08 +08 +08 +08 +08 +88 +70 00 00 ENDCHAR -STARTCHAR 004b +STARTCHAR K ENCODING 75 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -42 -44 -48 -50 -70 -48 -48 -44 -42 -42 +84 +88 +90 +a0 +c0 +a0 +90 +88 +84 00 00 ENDCHAR -STARTCHAR 004c +STARTCHAR L ENCODING 76 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -40 -40 -40 -40 -40 -40 -40 -40 -40 -7E +80 +80 +80 +80 +80 +80 +80 +80 +fc 00 00 ENDCHAR -STARTCHAR 004d +STARTCHAR M ENCODING 77 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -42 -46 -66 -6A -5A -52 -52 -42 -42 -42 +84 +cc +cc +b4 +b4 +84 +84 +84 +84 00 00 ENDCHAR -STARTCHAR 004e +STARTCHAR N ENCODING 78 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -62 -62 -52 -52 -52 -4A -4A -4A -46 -46 +84 +84 +c4 +a4 +94 +8c +84 +84 +84 00 00 ENDCHAR -STARTCHAR 004f +STARTCHAR O ENCODING 79 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -42 -42 -42 -42 -42 -42 -3C +78 +84 +84 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR -STARTCHAR 0050 +STARTCHAR P ENCODING 80 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7C -42 -42 -42 -42 -7C -40 -40 -40 -40 +f8 +84 +84 +84 +f8 +80 +80 +80 +80 00 00 ENDCHAR -STARTCHAR 0051 +STARTCHAR Q ENCODING 81 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -42 -42 -42 -72 -4A -46 -3C +78 +84 +84 +84 +84 +84 +a4 +94 +78 04 -02 +00 ENDCHAR -STARTCHAR 0052 +STARTCHAR R ENCODING 82 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7C -42 -42 -42 -7C -44 -42 -42 -42 -42 +f8 +84 +84 +84 +f8 +a0 +90 +88 +84 00 00 ENDCHAR -STARTCHAR 0053 +STARTCHAR S ENCODING 83 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -20 -10 -08 +78 +84 +80 +80 +78 04 -42 -42 -3C +04 +84 +78 00 00 ENDCHAR -STARTCHAR 0054 +STARTCHAR T ENCODING 84 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7E -10 -10 -10 -10 -10 -10 -10 -10 -10 +f8 +20 +20 +20 +20 +20 +20 +20 +20 00 00 ENDCHAR -STARTCHAR 0055 +STARTCHAR U ENCODING 85 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -42 -42 -42 -42 -42 -42 -42 -42 -42 -3C +84 +84 +84 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR -STARTCHAR 0056 +STARTCHAR V ENCODING 86 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -42 -42 -42 -44 -24 -24 -28 -18 -10 -10 -00 -00 -ENDCHAR -STARTCHAR 0057 -ENCODING 87 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -4A -4A -4A -4A -4A -7E -24 -24 -24 -24 -00 -00 -ENDCHAR -STARTCHAR 0058 -ENCODING 88 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -42 -42 -24 -24 -18 -18 -24 -24 -42 -42 -00 -00 -ENDCHAR -STARTCHAR 0059 -ENCODING 89 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -42 -42 -44 -24 -28 -18 -10 -10 -10 -10 -00 -00 -ENDCHAR -STARTCHAR 005a -ENCODING 90 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -7E -02 -04 -08 -08 -10 -20 -20 -40 -7E -00 -00 -ENDCHAR -STARTCHAR 005b -ENCODING 91 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -1E -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -1E -ENDCHAR -STARTCHAR 005c -ENCODING 92 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -40 -40 -20 -20 -10 -10 -10 -08 -08 -04 -04 -02 -02 -ENDCHAR -STARTCHAR 005d -ENCODING 93 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -78 -08 -08 -08 -08 -08 -08 -08 -08 -08 -08 -08 -78 -ENDCHAR -STARTCHAR 005e -ENCODING 94 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -18 -24 -42 -00 -00 -00 -00 -00 -00 -00 -00 -00 -00 -00 -ENDCHAR -STARTCHAR 005f -ENCODING 95 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -00 -00 -00 -00 -00 -00 -00 -00 -7E -ENDCHAR -STARTCHAR 0060 -ENCODING 96 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -0C -08 -08 -04 -00 -00 -00 -00 -00 -00 -00 -00 -00 -00 -ENDCHAR -STARTCHAR 0061 -ENCODING 97 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3C -42 -0E -32 -42 -46 -3A -00 -00 -ENDCHAR -STARTCHAR 0062 -ENCODING 98 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -40 -40 -40 -5C -62 -42 -42 -42 -62 -5C -00 -00 -ENDCHAR -STARTCHAR 0063 -ENCODING 99 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3C -42 -40 -40 -40 -42 -3C -00 -00 -ENDCHAR -STARTCHAR 0064 -ENCODING 100 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -02 -02 -02 -3A -46 -42 -42 -42 -46 -3A -00 -00 -ENDCHAR -STARTCHAR 0065 -ENCODING 101 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3C -42 -42 -7E -40 -42 -3C -00 -00 -ENDCHAR -STARTCHAR 0066 -ENCODING 102 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -0C -12 -10 -10 -7C -10 -10 -10 -10 -10 -00 -00 -ENDCHAR -STARTCHAR 0067 -ENCODING 103 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3A -44 -44 -44 -38 -20 -5C -42 -3C -ENDCHAR -STARTCHAR 0068 -ENCODING 104 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -40 -40 -40 -5C -62 -42 -42 -42 -42 -42 -00 -00 -ENDCHAR -STARTCHAR 0069 -ENCODING 105 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -10 -10 -00 -10 -10 -10 -10 -10 -10 -10 -00 -00 -ENDCHAR -STARTCHAR 006a -ENCODING 106 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -04 -04 -00 -04 -04 -04 -04 -04 -04 -04 -44 -38 -ENDCHAR -STARTCHAR 006b -ENCODING 107 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -40 -40 -40 -44 +84 +84 +84 48 -50 -70 48 -44 -42 -00 -00 -ENDCHAR -STARTCHAR 006c -ENCODING 108 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -00 -00 -ENDCHAR -STARTCHAR 006d -ENCODING 109 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -7C -52 -52 -52 -52 -52 -52 -00 -00 -ENDCHAR -STARTCHAR 006e -ENCODING 110 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -5C -62 -42 -42 -42 -42 -42 -00 -00 -ENDCHAR -STARTCHAR 006f -ENCODING 111 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3C -42 -42 -42 -42 -42 -3C -00 -00 -ENDCHAR -STARTCHAR 0070 -ENCODING 112 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -5C -62 -42 -42 -42 -62 -5C -40 -40 -ENDCHAR -STARTCHAR 0071 -ENCODING 113 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3A -46 -42 -42 -42 -46 -3A -02 -02 -ENDCHAR -STARTCHAR 0072 -ENCODING 114 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -5C -62 -42 -40 -40 -40 -40 -00 -00 -ENDCHAR -STARTCHAR 0073 -ENCODING 115 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3C -42 -20 -18 -04 -42 -3C -00 -00 -ENDCHAR -STARTCHAR 0074 -ENCODING 116 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -10 -10 -10 -7E -10 -10 -10 -10 -10 -0E -00 -00 -ENDCHAR -STARTCHAR 0075 -ENCODING 117 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -42 -42 -42 -42 -42 -46 -3A -00 -00 -ENDCHAR -STARTCHAR 0076 -ENCODING 118 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -42 -42 -22 -24 -14 -18 -08 -00 -00 -ENDCHAR -STARTCHAR 0077 -ENCODING 119 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -4A -4A -4A -7E -24 -24 -24 -00 -00 -ENDCHAR -STARTCHAR 0078 -ENCODING 120 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -42 -42 -24 -18 -24 -42 -42 -00 -00 -ENDCHAR -STARTCHAR 0079 -ENCODING 121 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -42 -42 -22 -24 -14 -1C -08 48 30 +30 +30 +00 +00 ENDCHAR -STARTCHAR 007a +STARTCHAR W +ENCODING 87 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +84 +84 +84 +84 +b4 +b4 +cc +cc +84 +00 +00 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +84 +84 +48 +48 +30 +48 +48 +84 +84 +00 +00 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +88 +88 +50 +50 +20 +20 +20 +20 +20 +00 +00 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +fc +04 +08 +10 +30 +20 +40 +80 +fc +00 +00 +ENDCHAR +STARTCHAR [ +ENCODING 91 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +78 +40 +40 +40 +40 +40 +40 +40 +78 +00 +00 +ENDCHAR +STARTCHAR \ +ENCODING 92 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +40 +40 +20 +20 +10 +08 +08 +04 +04 +00 +00 +ENDCHAR +STARTCHAR ] +ENCODING 93 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +78 +08 +08 +08 +08 +08 +08 +08 +78 +00 +00 +ENDCHAR +STARTCHAR ^ +ENCODING 94 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +10 +28 +44 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR _ +ENCODING 95 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +fc +00 +ENDCHAR +STARTCHAR ` +ENCODING 96 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +70 +30 +08 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +78 +04 +7c +84 +8c +74 +00 +00 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +80 +80 +80 +b8 +c4 +84 +84 +c4 +b8 +00 +00 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +78 +84 +80 +80 +84 +78 +00 +00 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +04 +04 +04 +74 +8c +84 +84 +8c +74 +00 +00 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +78 +84 +fc +80 +84 +78 +00 +00 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +38 +44 +40 +40 +f0 +40 +40 +40 +40 +00 +00 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +74 +88 +88 +70 +80 +78 +84 +78 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +80 +80 +80 +b8 +c4 +84 +84 +84 +84 +00 +00 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +20 +00 +60 +20 +20 +20 +20 +f8 +00 +00 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +08 +00 +18 +08 +08 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +80 +80 +80 +88 +90 +e0 +90 +88 +84 +00 +00 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +60 +20 +20 +20 +20 +20 +20 +20 +f8 +00 +00 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +d0 +a8 +a8 +a8 +a8 +88 +00 +00 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +b8 +c4 +84 +84 +84 +84 +00 +00 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +78 +84 +84 +84 +84 +78 +00 +00 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +b8 +c4 +84 +c4 +b8 +80 +80 +80 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +74 +8c +84 +8c +74 +04 +04 +04 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +b8 +44 +40 +40 +40 +40 +00 +00 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +78 +84 +60 +18 +84 +78 +00 +00 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +40 +40 +f0 +40 +40 +40 +44 +38 +00 +00 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +84 +84 +84 +84 +8c +74 +00 +00 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +88 +88 +88 +50 +50 +20 +00 +00 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +88 +88 +a8 +a8 +a8 +50 +00 +00 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +84 +48 +30 +30 +48 +84 +00 +00 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +84 +84 +84 +8c +74 +04 +84 +78 +ENDCHAR +STARTCHAR z ENCODING 122 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -7E -04 +fc 08 10 -10 20 -7E +40 +fc 00 00 ENDCHAR -STARTCHAR 007b +STARTCHAR { ENCODING 123 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -06 -08 -08 -08 -08 -08 -10 -08 -08 -08 -08 -08 -06 -ENDCHAR -STARTCHAR 007c -ENCODING 124 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -ENDCHAR -STARTCHAR 007d -ENCODING 125 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -60 -10 -10 -10 -10 -10 -08 -10 -10 -10 -10 -10 -60 -ENDCHAR -STARTCHAR 007e -ENCODING 126 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP 00 +1c 20 -52 -4A -04 +20 +10 +60 +10 +20 +20 +1c 00 00 +ENDCHAR +STARTCHAR | +ENCODING 124 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +10 +10 +10 +10 +10 +10 +10 +10 +10 +00 +00 +ENDCHAR +STARTCHAR } +ENCODING 125 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +70 +08 +08 +10 +0c +10 +08 +08 +70 +00 +00 +ENDCHAR +STARTCHAR ~ +ENCODING 126 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +24 +54 +48 +00 00 00 00 @@ -2380,11 +2585,11 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 007f +STARTCHAR (Blank) ENCODING 127 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2399,13 +2604,12 @@ BITMAP 00 00 00 -00 ENDCHAR STARTCHAR 00a0 ENCODING 160 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2420,18 +2624,16 @@ BITMAP 00 00 00 -00 ENDCHAR STARTCHAR 00a1 ENCODING 161 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 10 -10 00 10 10 @@ -2445,93 +2647,89 @@ BITMAP ENDCHAR STARTCHAR 00a2 ENCODING 162 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 +10 +38 +54 +50 +50 +54 +38 +10 00 00 -10 -3e -52 -50 -50 -50 -52 -3e -10 00 ENDCHAR STARTCHAR 00a3 ENCODING 163 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -00 -18 -24 -20 -20 -78 -20 -20 -78 -24 +38 +44 +40 +40 +e0 +40 +40 +44 +b8 00 00 ENDCHAR STARTCHAR 00a4 ENCODING 164 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 -42 -3c -24 -24 -3c -42 -00 +84 +78 +48 +48 +78 +84 00 00 00 ENDCHAR STARTCHAR 00a5 ENCODING 165 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -42 -24 -18 -7e -08 -08 -7e -08 -08 -08 +88 +88 +50 +50 +f8 +20 +f8 +20 +20 00 00 ENDCHAR STARTCHAR 00a6 ENCODING 166 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2540,7 +2738,6 @@ BITMAP 10 10 00 -00 10 10 10 @@ -2550,35 +2747,33 @@ BITMAP ENDCHAR STARTCHAR 00a7 ENCODING 167 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -3c -42 -20 -18 -24 -42 -24 -18 -04 -42 -3c +30 +48 +40 +30 +48 +48 +30 +08 +48 +30 00 00 ENDCHAR STARTCHAR 00a8 ENCODING 168 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -48 -48 00 +6c 00 00 00 @@ -2592,41 +2787,39 @@ BITMAP ENDCHAR STARTCHAR 00a9 ENCODING 169 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -3c -42 -5a -66 -62 -62 -62 -66 -5a -42 -3c +78 +84 +b4 +a4 +a4 +a4 +b4 +84 +78 +00 00 00 ENDCHAR STARTCHAR 00aa ENCODING 170 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -1c -22 -1e -22 -26 -1a 00 -3e +38 +04 +3c +44 +3c 00 +7c 00 00 00 @@ -2634,30 +2827,29 @@ BITMAP ENDCHAR STARTCHAR 00ab ENCODING 171 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 -00 -00 -0a 14 28 50 +a0 +50 28 14 -0a +00 00 00 ENDCHAR STARTCHAR 00ac ENCODING 172 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2665,20 +2857,19 @@ BITMAP 00 00 00 +7c +04 +04 00 00 -f8 -08 -08 -08 00 00 ENDCHAR STARTCHAR 00ad ENCODING 173 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2686,10 +2877,9 @@ BITMAP 00 00 00 +7c 00 00 -f0 -00 00 00 00 @@ -2697,35 +2887,33 @@ f0 ENDCHAR STARTCHAR 00ae ENCODING 174 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -3c -42 -7a -66 -66 -7a -66 -66 -66 -42 -3c +78 +84 +b4 +ac +ac +b4 +ac +84 +78 +00 00 00 ENDCHAR STARTCHAR 00af ENCODING 175 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -f0 -00 +7c 00 00 00 @@ -2739,11 +2927,12 @@ f0 ENDCHAR STARTCHAR 00b0 ENCODING 176 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +00 30 48 48 @@ -2755,44 +2944,40 @@ BITMAP 00 00 00 -00 -00 ENDCHAR STARTCHAR 00b1 ENCODING 177 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 -00 -00 -00 10 10 7c 10 10 +00 7c 00 00 +00 ENDCHAR STARTCHAR 00b2 ENCODING 178 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -30 -48 -08 -10 +40 +a0 20 40 -78 +80 +e0 00 00 00 @@ -2802,18 +2987,17 @@ BITMAP ENDCHAR STARTCHAR 00b3 ENCODING 179 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -30 -48 -08 -30 -08 -48 -30 +e0 +20 +40 +20 +a0 +40 00 00 00 @@ -2823,15 +3007,14 @@ BITMAP ENDCHAR STARTCHAR 00b4 ENCODING 180 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -08 10 20 -40 +00 00 00 00 @@ -2844,51 +3027,49 @@ BITMAP ENDCHAR STARTCHAR 00b5 ENCODING 181 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 +84 +84 +84 +84 +cc +b4 +80 00 -44 -44 -44 -44 -6c -54 -40 -40 ENDCHAR STARTCHAR 00b6 ENCODING 182 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -54 -54 -54 -54 -34 -14 -14 -14 -14 -14 -1c +7c +e8 +e8 +e8 +68 +28 +28 +28 +28 +00 +00 ENDCHAR STARTCHAR 00b7 ENCODING 183 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2896,8 +3077,7 @@ BITMAP 00 00 00 -10 -00 +30 00 00 00 @@ -2907,9 +3087,9 @@ BITMAP ENDCHAR STARTCHAR 00b8 ENCODING 184 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2923,23 +3103,21 @@ BITMAP 00 00 10 -10 20 ENDCHAR STARTCHAR 00b9 ENCODING 185 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -20 -60 -20 -20 -20 -20 +40 +c0 +40 +40 +40 +e0 00 00 00 @@ -2949,19 +3127,18 @@ BITMAP ENDCHAR STARTCHAR 00ba ENCODING 186 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -24 -24 -18 -00 -3c +30 +48 +48 +30 00 +78 00 00 00 @@ -2970,732 +3147,697 @@ BITMAP ENDCHAR STARTCHAR 00bb ENCODING 187 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 -00 -00 +a0 50 28 14 -0a -14 28 50 +a0 +00 00 00 ENDCHAR STARTCHAR 00bc ENCODING 188 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -20 -62 -24 -24 -28 -12 -16 -2a -4e -42 +40 +c0 +40 +40 +44 +ec +14 +14 +1c +04 00 00 ENDCHAR STARTCHAR 00bd ENCODING 189 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -20 -62 -24 -24 -28 -14 -1a -22 -44 -4e +40 +c0 +40 +40 +48 +f4 +04 +08 +10 +1c 00 00 ENDCHAR STARTCHAR 00be ENCODING 190 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -62 -12 -24 -18 -68 -12 -26 -2a -4e -02 +e0 +20 +40 +20 +a4 +4c +14 +14 +1c +04 00 00 ENDCHAR STARTCHAR 00bf ENCODING 191 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 +20 +00 +20 +20 +40 +80 +84 +84 +78 00 -08 -08 00 -08 -08 -08 -08 -04 -42 -42 -3c ENDCHAR STARTCHAR 00c0 ENCODING 192 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -20 -18 00 -18 -28 -24 -44 -42 -7E -42 -42 -42 +20 +10 +00 +30 +48 +84 +84 +fc +84 +84 00 00 ENDCHAR STARTCHAR 00c1 ENCODING 193 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -04 -18 00 -18 -28 -24 -44 -42 -7E -42 -42 -42 +10 +20 +00 +30 +48 +84 +84 +fc +84 +84 00 00 ENDCHAR STARTCHAR 00c2 ENCODING 194 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -24 00 -18 -28 -24 -44 -42 -7E -42 -42 -42 +30 +48 +00 +30 +48 +84 +84 +fc +84 +84 00 00 ENDCHAR STARTCHAR 00c3 ENCODING 195 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -14 -28 00 -18 28 -24 -44 -42 -7E -42 -42 -42 +50 +00 +30 +48 +84 +84 +fc +84 +84 00 00 ENDCHAR STARTCHAR 00c4 ENCODING 196 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -24 +48 +48 00 -18 -28 -24 -44 -42 -7E -42 -42 -42 +30 +48 +84 +84 +fc +84 +84 00 00 ENDCHAR STARTCHAR 00c5 ENCODING 197 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -10 00 -10 -18 -28 -24 -44 -42 -7E -42 -42 -42 +30 +48 +30 +30 +48 +84 +84 +fc +84 +84 00 00 ENDCHAR STARTCHAR 00c6 ENCODING 198 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3E -50 -50 -50 -9C -f0 -90 -90 -90 -9E +5c +a0 +a0 +a0 +b8 +e0 +a0 +a0 +bc 00 00 ENDCHAR STARTCHAR 00c7 ENCODING 199 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3C -42 -42 -40 -40 -40 -40 -42 -42 -3C -08 +78 +84 +80 +80 +80 +80 +80 +84 +78 10 +20 ENDCHAR STARTCHAR 00c8 ENCODING 200 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -20 -18 00 -7e -40 -40 -40 -7c -40 -40 -40 -7E +20 +10 +00 +fc +80 +80 +f0 +80 +80 +fc 00 00 ENDCHAR STARTCHAR 00c9 ENCODING 201 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -04 -18 00 -7e -40 -40 -40 -7c -40 -40 -40 -7E +10 +20 +00 +fc +80 +80 +f0 +80 +80 +fc 00 00 ENDCHAR STARTCHAR 00ca ENCODING 202 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -24 00 -7e -40 -40 -40 -7c -40 -40 -40 -7E +30 +48 +00 +fc +80 +80 +f0 +80 +80 +fc 00 00 ENDCHAR STARTCHAR 00cb ENCODING 203 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -24 +48 +48 00 -7e -40 -40 -40 -7c -40 -40 -40 -7E +fc +80 +80 +f0 +80 +80 +fc 00 00 ENDCHAR STARTCHAR 00cc ENCODING 204 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -10 -0c 00 -3e -08 -08 -08 -08 -08 -08 -08 -3E +20 +10 +00 +7c +10 +10 +10 +10 +10 +7c 00 00 ENDCHAR STARTCHAR 00cd ENCODING 205 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -04 -18 00 -3e -08 -08 -08 -08 -08 -08 -08 -3E +10 +20 +00 +7c +10 +10 +10 +10 +10 +7c 00 00 ENDCHAR STARTCHAR 00ce ENCODING 206 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -08 -14 00 -3e -08 -08 -08 -08 -08 -08 -08 -3E +30 +48 +00 +7c +10 +10 +10 +10 +10 +7c 00 00 ENDCHAR STARTCHAR 00cf ENCODING 207 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -14 +28 +28 00 -3e -08 -08 -08 -08 -08 -08 -08 -3E +7c +10 +10 +10 +10 +10 +7c 00 00 ENDCHAR STARTCHAR 00d0 ENCODING 208 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -78 +f8 44 -42 -42 -e2 -42 -42 -42 44 -78 +44 +e4 +44 +44 +44 +f8 00 00 ENDCHAR STARTCHAR 00d1 ENCODING 209 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -14 -28 00 -62 -52 -52 -52 -4A -4A -4A -46 -46 +28 +50 +00 +84 +c4 +a4 +a4 +94 +8c +84 00 00 ENDCHAR STARTCHAR 00d2 ENCODING 210 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -20 -18 00 -3c -42 -42 -42 -42 -42 -42 -42 -3C +20 +10 +00 +78 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00d3 ENCODING 211 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -04 -18 00 -3c -42 -42 -42 -42 -42 -42 -42 -3C +10 +20 +00 +78 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00d4 ENCODING 212 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -24 00 -3c -42 -42 -42 -42 -42 -42 -42 -3C +30 +48 +00 +78 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00d5 ENCODING 213 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -14 -28 00 -3c -42 -42 -42 -42 -42 -42 -42 -3C +28 +50 +00 +78 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00d6 ENCODING 214 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -24 +48 +48 00 -3c -42 -42 -42 -42 -42 -42 -42 -3C +78 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00d7 ENCODING 215 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 +84 +48 +30 +30 +48 +84 00 -82 -44 -28 -10 -28 -44 -82 00 00 ENDCHAR STARTCHAR 00d8 ENCODING 216 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -02 -02 -3C -46 -4a -4a -4a -52 -52 -52 -62 -3C -40 -40 +00 +04 +78 +8c +94 +94 +a4 +a4 +a4 +c4 +78 +80 +00 ENDCHAR STARTCHAR 00d9 ENCODING 217 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -20 -18 00 -42 -42 -42 -42 -42 -42 -42 -42 -3C +20 +10 +00 +84 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00da ENCODING 218 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -04 -18 00 -42 -42 -42 -42 -42 -42 -42 -42 -3C +10 +20 +00 +84 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00db ENCODING 219 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -24 00 -42 -42 -42 -42 -42 -42 -42 -42 -3C +30 +48 +00 +84 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00dc ENCODING 220 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -24 +48 +48 00 -42 -42 -42 -42 -42 -42 -42 -42 -3C +84 +84 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00dd ENCODING 221 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -04 -18 -42 -42 +00 +10 +20 +00 +44 44 -24 28 -18 10 10 10 @@ -3705,716 +3847,682 @@ BITMAP ENDCHAR STARTCHAR 00de ENCODING 222 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -40 -40 -7c -42 -42 -42 -42 -7c -40 -40 +80 +f8 +84 +84 +84 +f8 +80 +80 +80 00 00 ENDCHAR STARTCHAR 00df ENCODING 223 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -24 -24 -24 -38 -24 -22 -22 -22 -7c 00 +78 +84 +84 +f8 +84 +84 +c4 +b8 +80 00 ENDCHAR STARTCHAR 00e0 ENCODING 224 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 20 10 -08 00 -3C -42 -0E -32 -42 -46 -3A +00 +78 +04 +7c +84 +8c +74 00 00 ENDCHAR STARTCHAR 00e1 ENCODING 225 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -04 -08 10 +20 00 -3C -42 -0E -32 -42 -46 -3A +00 +78 +04 +7c +84 +8c +74 00 00 ENDCHAR STARTCHAR 00e2 ENCODING 226 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +30 +48 00 -18 -24 00 -3C -42 -0E -32 -42 -46 -3A +78 +04 +7c +84 +8c +74 00 00 ENDCHAR STARTCHAR 00e3 ENCODING 227 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -14 28 +50 00 -3C -42 -0E -32 -42 -46 -3A +00 +78 +04 +7c +84 +8c +74 00 00 ENDCHAR STARTCHAR 00e4 ENCODING 228 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +48 +48 00 00 -24 -00 -3C -42 -0E -32 -42 -46 -3A +78 +04 +7c +84 +8c +74 00 00 ENDCHAR STARTCHAR 00e5 ENCODING 229 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -10 -28 -10 +30 +48 +30 00 -3C -42 -0E -32 -42 -46 -3A +78 +04 +7c +84 +8c +74 00 00 ENDCHAR STARTCHAR 00e6 ENCODING 230 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -7C -92 -32 -5E +68 +14 +7c 90 -92 -7C +94 +68 00 00 ENDCHAR STARTCHAR 00e7 ENCODING 231 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -3C -42 -40 -40 -40 -42 -3C -08 +78 +84 +80 +80 +84 +78 10 +20 ENDCHAR STARTCHAR 00e8 ENCODING 232 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 20 10 -08 00 -3C -42 -42 -7E -40 -42 -3C +00 +78 +84 +fc +80 +84 +78 00 00 ENDCHAR STARTCHAR 00e9 ENCODING 233 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -04 -08 10 +20 00 -3C -42 -42 -7E -40 -42 -3C +00 +78 +84 +fc +80 +84 +78 00 00 ENDCHAR STARTCHAR 00ea ENCODING 234 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +30 +48 00 -18 -24 00 -3C -42 -42 -7E -40 -42 -3C +78 +84 +fc +80 +84 +78 00 00 ENDCHAR STARTCHAR 00eb ENCODING 235 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +48 +48 00 00 -24 -00 -3C -42 -42 -7E -40 -42 -3C +78 +84 +fc +80 +84 +78 00 00 ENDCHAR STARTCHAR 00ec ENCODING 236 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 20 10 -08 00 +00 +30 10 10 10 10 -10 -10 -10 +7c 00 00 ENDCHAR STARTCHAR 00ed ENCODING 237 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -08 10 20 00 +00 +30 10 10 10 10 -10 -10 -10 +7c 00 00 ENDCHAR STARTCHAR 00ee ENCODING 238 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +30 +48 00 -10 -28 00 +30 10 10 10 10 -10 -10 -10 +7c 00 00 ENDCHAR STARTCHAR 00ef ENCODING 239 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +48 +48 00 00 -28 -00 -10 -10 -10 +30 10 10 10 10 +7c 00 00 ENDCHAR STARTCHAR 00f0 ENCODING 240 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -28 -10 -28 -04 -3c -44 -44 -44 -44 -44 -38 +48 +30 +50 +08 +78 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00f1 ENCODING 241 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -14 28 +50 00 -5C -62 -42 -42 -42 -42 -42 +00 +b8 +c4 +84 +84 +84 +84 00 00 ENDCHAR STARTCHAR 00f2 ENCODING 242 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 20 10 -08 00 -3C -42 -42 -42 -42 -42 -3C +00 +78 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00f3 ENCODING 243 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -04 -08 10 +20 00 -3C -42 -42 -42 -42 -42 -3C +00 +78 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00f4 ENCODING 244 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +30 +48 00 -18 -24 00 -3C -42 -42 -42 -42 -42 -3C +78 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00f5 ENCODING 245 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -14 28 +50 00 -3C -42 -42 -42 -42 -42 -3C +00 +78 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00f6 ENCODING 246 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +48 +48 00 00 -24 -00 -3C -42 -42 -42 -42 -42 -3C +78 +84 +84 +84 +84 +78 00 00 ENDCHAR STARTCHAR 00f7 ENCODING 247 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 +10 +10 00 +7c 00 +10 +10 00 00 -30 -00 -fc -00 -30 -00 00 ENDCHAR STARTCHAR 00f8 ENCODING 248 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 -02 +00 04 -3C -4a -4a -52 -52 -62 -3C -40 -40 +78 +8c +94 +a4 +c4 +78 +80 +00 ENDCHAR STARTCHAR 00f9 ENCODING 249 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 20 10 -08 -42 -42 -42 -42 -42 -46 -3A +00 +00 +84 +84 +84 +84 +8c +74 00 00 ENDCHAR STARTCHAR 00fa ENCODING 250 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -04 -08 10 -42 -42 -42 -42 -42 -46 -3A +20 +00 +00 +84 +84 +84 +84 +8c +74 00 00 ENDCHAR STARTCHAR 00fb ENCODING 251 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +30 +48 00 -18 -24 00 -42 -42 -42 -42 -42 -46 -3A +84 +84 +84 +84 +8c +74 00 00 ENDCHAR STARTCHAR 00fc ENCODING 252 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +48 +48 00 00 -24 -00 -42 -42 -42 -42 -42 -46 -3A +84 +84 +84 +84 +8c +74 00 00 ENDCHAR STARTCHAR 00fd ENCODING 253 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -04 -08 10 -42 -42 -22 -24 -14 -1C -08 -48 -30 +20 +00 +00 +84 +84 +84 +8c +74 +04 +84 +78 ENDCHAR STARTCHAR 00fe ENCODING 254 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -40 -40 -40 -5C -62 -42 -42 -42 -62 -5C -40 -40 +00 +80 +80 +b8 +c4 +84 +84 +c4 +b8 +80 +80 ENDCHAR STARTCHAR 00ff ENCODING 255 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -00 -24 -00 -42 -42 -22 -24 -14 -1C -08 48 -30 +48 +00 +00 +84 +84 +84 +8c +74 +04 +84 +78 ENDCHAR ENDFONT diff --git a/resource/font/7x14B.bdf b/resource/font/7x13B.bdf similarity index 53% rename from resource/font/7x14B.bdf rename to resource/font/7x13B.bdf index a99d925..ee3828c 100644 --- a/resource/font/7x14B.bdf +++ b/resource/font/7x13B.bdf @@ -1,12 +1,16 @@ STARTFONT 2.1 -COMMENT -COMMENT Donated by H. Kagotani ; public domain -COMMENT font from Japan -COMMENT -FONT -Misc-Fixed-Bold-R-Normal--14-130-75-75-C-70-ISO8859-1 -SIZE 7 75 75 -FONTBOUNDINGBOX 7 14 0 -2 -STARTPROPERTIES 19 +COMMENT "" +COMMENT Designed by Stephen Gildea from original designs. +COMMENT November 1989 +COMMENT "" +COMMENT Characters above 127 designed and made by +COMMENT Thomas Bagli (pyramid!pcsbst!tom@uunet.UU.NET) +COMMENT PCS Computer Systeme, West Germany +COMMENT "" +FONT -Misc-Fixed-Bold-R-Normal--13-120-75-75-C-70-ISO8859-1 +SIZE 13 78 78 +FONTBOUNDINGBOX 7 13 0 -2 +STARTPROPERTIES 21 FONTNAME_REGISTRY "" FOUNDRY "Misc" FAMILY_NAME "Fixed" @@ -14,88 +18,267 @@ WEIGHT_NAME "Bold" SLANT "R" SETWIDTH_NAME "Normal" ADD_STYLE_NAME "" -PIXEL_SIZE 14 -POINT_SIZE 130 +PIXEL_SIZE 13 +POINT_SIZE 120 RESOLUTION_X 75 RESOLUTION_Y 75 SPACING "C" AVERAGE_WIDTH 70 CHARSET_REGISTRY "ISO8859" CHARSET_ENCODING "1" -DEFAULT_CHAR 32 +UNDERLINE_POSITION -1 +DESTINATION 1 +DEFAULT_CHAR 0 FONT_DESCENT 2 -FONT_ASCENT 12 +FONT_ASCENT 11 COPYRIGHT "Public domain font. Share and enjoy." ENDPROPERTIES -CHARS 209 -STARTCHAR 0001 +CHARS 224 +STARTCHAR C000 +ENCODING 0 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +7c +7c +7c +7c +7c +7c +7c +7c +7c +7c +7c +00 +ENDCHAR +STARTCHAR C001 ENCODING 1 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -18 -3c -3c -7e -7e -3c -3c -18 -18 +00 +00 +00 +30 +78 +fc +78 +30 +00 00 00 ENDCHAR -STARTCHAR 0002 +STARTCHAR C002 ENCODING 2 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -76 -ee -dc -ba -76 -ee -dc -ba -76 -ee -dc -ba -76 -ee +00 +cc +30 +cc +30 +cc +30 +cc +30 +cc +30 +cc +00 ENDCHAR -STARTCHAR 000b +STARTCHAR C003 +ENCODING 3 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +d8 +d8 +f8 +d8 +d8 +00 +3c +18 +18 +18 +18 +00 +ENDCHAR +STARTCHAR C004 +ENCODING 4 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +f0 +c0 +e0 +c0 +c0 +00 +3c +30 +38 +30 +30 +00 +ENDCHAR +STARTCHAR C005 +ENCODING 5 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +70 +c0 +c0 +c0 +70 +00 +38 +34 +38 +34 +34 +00 +ENDCHAR +STARTCHAR C006 +ENCODING 6 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +c0 +c0 +c0 +c0 +f0 +00 +3c +30 +38 +30 +30 +00 +ENDCHAR +STARTCHAR C007 +ENCODING 7 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +78 +cc +cc +78 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C010 +ENCODING 8 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +30 +30 +fc +fc +30 +30 +00 +fc +fc +00 +00 +ENDCHAR +STARTCHAR C011 +ENCODING 9 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +cc +ec +fc +dc +cc +00 +30 +30 +30 +30 +3c +00 +ENDCHAR +STARTCHAR C012 +ENCODING 10 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +cc +cc +48 +78 +30 +00 +3c +18 +18 +18 +18 +00 +ENDCHAR +STARTCHAR C013 ENCODING 11 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -18 -18 -18 -18 -18 -f8 -f8 -00 +30 +30 +30 +30 +30 +30 +f0 +f0 00 00 00 00 00 ENDCHAR -STARTCHAR 000c +STARTCHAR C014 ENCODING 12 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -103,20 +286,19 @@ BITMAP 00 00 00 -f8 -f8 -18 -18 -18 -18 -18 -18 +f0 +f0 +30 +30 +30 +30 +30 ENDCHAR -STARTCHAR 000d +STARTCHAR C015 ENCODING 13 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -124,63 +306,62 @@ BITMAP 00 00 00 -1e -1e -18 -18 -18 -18 -18 -18 +3e +3e +30 +30 +30 +30 +30 ENDCHAR -STARTCHAR 000e +STARTCHAR C016 ENCODING 14 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -18 -18 -18 -18 -18 -1e -1e -00 +30 +30 +30 +30 +30 +30 +3e +3e 00 00 00 00 00 ENDCHAR -STARTCHAR 000f +STARTCHAR C017 ENCODING 15 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -18 -18 -18 -18 -18 +30 +30 +30 +30 +30 +30 fe fe -18 -18 -18 -18 -18 -18 +30 +30 +30 +30 +30 ENDCHAR -STARTCHAR 0010 +STARTCHAR C020 ENCODING 16 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP +00 +00 fe fe 00 @@ -192,19 +373,17 @@ fe 00 00 00 -00 -00 -00 ENDCHAR -STARTCHAR 0011 +STARTCHAR C021 ENCODING 17 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 +00 fe fe 00 @@ -214,14 +393,12 @@ fe 00 00 00 -00 -00 ENDCHAR -STARTCHAR 0012 +STARTCHAR C022 ENCODING 18 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -236,13 +413,12 @@ fe 00 00 00 -00 ENDCHAR -STARTCHAR 0013 +STARTCHAR C023 ENCODING 19 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -252,18 +428,17 @@ BITMAP 00 00 00 -00 fe fe 00 00 00 ENDCHAR -STARTCHAR 0014 +STARTCHAR C024 ENCODING 20 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -275,65 +450,62 @@ BITMAP 00 00 00 -00 -00 fe fe +00 ENDCHAR -STARTCHAR 0015 +STARTCHAR C025 ENCODING 21 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -18 -18 -18 -18 -18 -1e -1e -18 -18 -18 -18 -18 -18 +30 +30 +30 +30 +30 +30 +3e +3e +30 +30 +30 +30 +30 ENDCHAR -STARTCHAR 0016 +STARTCHAR C026 ENCODING 22 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -18 -18 -18 -18 -18 -f8 -f8 -18 -18 -18 -18 -18 -18 +30 +30 +30 +30 +30 +30 +f0 +f0 +30 +30 +30 +30 +30 ENDCHAR -STARTCHAR 0017 +STARTCHAR C027 ENCODING 23 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -18 -18 -18 -18 -18 +30 +30 +30 +30 +30 +30 fe fe 00 @@ -341,13 +513,12 @@ fe 00 00 00 -00 ENDCHAR -STARTCHAR 0018 +STARTCHAR C030 ENCODING 24 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -357,39 +528,157 @@ BITMAP 00 fe fe -18 -18 -18 -18 -18 -18 +30 +30 +30 +30 +30 ENDCHAR -STARTCHAR 0019 +STARTCHAR C031 ENCODING 25 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 ENDCHAR -STARTCHAR 0020 +STARTCHAR C032 +ENCODING 26 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +0c +18 +60 +c0 +60 +18 +0c +fc +fc +00 +00 +ENDCHAR +STARTCHAR C033 +ENCODING 27 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +c0 +60 +18 +0c +18 +60 +c0 +fc +fc +00 +00 +ENDCHAR +STARTCHAR C034 +ENCODING 28 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +fc +6c +6c +6c +ec +cc +00 +00 +ENDCHAR +STARTCHAR C035 +ENCODING 29 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +04 +0c +fc +fc +30 +fc +fc +c0 +80 +00 +00 +ENDCHAR +STARTCHAR C036 +ENCODING 30 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +38 +6c +60 +60 +f8 +60 +60 +6c +b8 +00 +00 +ENDCHAR +STARTCHAR C037 +ENCODING 31 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +00 +30 +30 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C040 ENCODING 32 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -404,38 +693,37 @@ BITMAP 00 00 00 -00 ENDCHAR -STARTCHAR 0021 +STARTCHAR ! ENCODING 33 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -18 -18 -18 -18 -18 -18 +30 +30 +30 +30 +30 +30 00 -18 -18 +30 +30 00 00 ENDCHAR -STARTCHAR 0022 +STARTCHAR " ENCODING 34 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -7e -36 -36 +00 +00 +6c +6c 6c 00 00 @@ -445,106 +733,99 @@ BITMAP 00 00 00 -00 -00 ENDCHAR -STARTCHAR 0023 +STARTCHAR # ENCODING 35 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -1e -1e -1e -7e -3c -3c -7e -78 -78 -78 +28 +28 +7c +7c +28 +7c +7c +28 +28 00 00 ENDCHAR -STARTCHAR 0024 +STARTCHAR $ ENCODING 36 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -3c -5a -5a -38 -1c -1a -5a -5a -3c -18 +30 +78 +b4 +b0 +78 +34 +b4 +78 +30 +00 00 ENDCHAR -STARTCHAR 0025 +STARTCHAR % ENCODING 37 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -36 -6e -6c -38 -08 -10 -1c -36 -76 -6c +e4 +ac +e8 +18 +30 +60 +5c +d4 +9c 00 00 ENDCHAR -STARTCHAR 0026 +STARTCHAR & ENCODING 38 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -1c -36 -36 -36 -1c -36 -6e -6c -6c -36 +70 +d8 +d8 +d8 +70 +d4 +dc +d8 +74 00 00 ENDCHAR -STARTCHAR 0027 +STARTCHAR ' ENCODING 39 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP +00 +00 +38 38 -18 -18 30 -00 -00 -00 +60 00 00 00 @@ -553,95 +834,91 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 0028 +STARTCHAR ( ENCODING 40 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -06 -0c -18 +00 18 30 30 -30 +60 +60 +60 30 30 18 -18 -0c -06 +00 +00 ENDCHAR -STARTCHAR 0029 +STARTCHAR ) ENCODING 41 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +00 60 30 +30 18 18 -0c -0c -0c -0c -0c -18 18 30 +30 60 +00 +00 ENDCHAR -STARTCHAR 002a +STARTCHAR * ENCODING 42 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 -5a -5a -3c -18 -18 -3c -5a -5a +00 +48 +30 +fc +fc +30 +48 00 00 00 ENDCHAR -STARTCHAR 002b +STARTCHAR + ENCODING 43 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 -18 -18 -18 -7e -18 -18 -18 +30 +30 +fc +fc +30 +30 00 00 00 ENDCHAR -STARTCHAR 002c +STARTCHAR , ENCODING 44 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -651,18 +928,17 @@ BITMAP 00 00 00 -00 -00 38 -18 -18 +38 30 +60 +00 ENDCHAR -STARTCHAR 002d +STARTCHAR - ENCODING 45 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -670,20 +946,19 @@ BITMAP 00 00 00 -7e -7e -00 +fc +fc 00 00 00 00 00 ENDCHAR -STARTCHAR 002e +STARTCHAR . ENCODING 46 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -694,1012 +969,963 @@ BITMAP 00 00 00 -00 -18 -18 -00 +30 +78 +30 00 ENDCHAR -STARTCHAR 002f +STARTCHAR / ENCODING 47 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -06 -06 -06 +00 0c 0c 18 18 -18 -30 30 60 60 -60 +c0 +c0 +00 +00 ENDCHAR -STARTCHAR 0030 +STARTCHAR 0 ENCODING 48 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -66 -66 -66 -66 -66 -66 -3c +30 +48 +cc +cc +cc +cc +cc +48 +30 00 00 ENDCHAR -STARTCHAR 0031 +STARTCHAR 1 ENCODING 49 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -38 -78 -18 -18 -18 -18 -18 -18 -7e +30 +70 +b0 +30 +30 +30 +30 +30 +fc 00 00 ENDCHAR -STARTCHAR 0032 +STARTCHAR 2 ENCODING 50 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -06 +78 +cc +cc 0c -0c -18 -30 +38 60 -7e +c0 +c0 +fc 00 00 ENDCHAR -STARTCHAR 0033 +STARTCHAR 3 ENCODING 51 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -06 -1c -06 -06 -66 -66 -3c +fc +0c +18 +30 +78 +0c +0c +cc +78 00 00 ENDCHAR -STARTCHAR 0034 +STARTCHAR 4 ENCODING 52 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -04 -0c 0c 1c 3c -2c 6c -7e -04 -04 +cc +cc +fc +0c +0c 00 00 ENDCHAR -STARTCHAR 0035 +STARTCHAR 5 ENCODING 53 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7e -60 -60 -7c -66 -06 -06 -66 -66 -3c +fc +c0 +c0 +f8 +cc +0c +0c +cc +78 00 00 ENDCHAR -STARTCHAR 0036 +STARTCHAR 6 ENCODING 54 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -1c -36 -66 -60 -7c -66 -66 -66 -66 -3c +78 +cc +c0 +c0 +f8 +cc +cc +cc +78 00 00 ENDCHAR -STARTCHAR 0037 +STARTCHAR 7 ENCODING 55 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7e -66 -6c +fc +0c 0c 18 18 -18 -18 -18 -18 +30 +30 +60 +60 00 00 ENDCHAR -STARTCHAR 0038 +STARTCHAR 8 ENCODING 56 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -3c -18 -3c -66 -66 -66 -3c +78 +cc +cc +cc +78 +cc +cc +cc +78 00 00 ENDCHAR -STARTCHAR 0039 +STARTCHAR 9 ENCODING 57 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -66 -66 -3e -06 -66 -6c -38 +78 +cc +cc +cc +7c +0c +0c +cc +78 00 00 ENDCHAR -STARTCHAR 003a +STARTCHAR : ENCODING 58 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 -18 -18 -00 -00 -00 -18 -18 +30 +78 +30 00 00 +30 +78 +30 00 ENDCHAR -STARTCHAR 003b +STARTCHAR ; ENCODING 59 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 -18 -18 -00 -00 -00 -38 -18 -18 +30 +78 30 00 +38 +38 +30 +60 +00 ENDCHAR -STARTCHAR 003c +STARTCHAR < ENCODING 60 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -00 -06 0c 18 30 60 +c0 +60 30 18 0c -06 00 00 ENDCHAR -STARTCHAR 003d +STARTCHAR = ENCODING 61 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 -7e -7e -00 -7e -7e +fc +fc 00 +fc +fc 00 00 00 00 ENDCHAR -STARTCHAR 003e +STARTCHAR > ENCODING 62 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -00 +c0 60 30 18 0c -06 -0c 18 30 60 +c0 00 00 ENDCHAR -STARTCHAR 003f +STARTCHAR ? ENCODING 63 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 +78 +cc +cc 0c -18 -18 -18 +38 +30 00 -18 -18 +30 +30 00 00 ENDCHAR -STARTCHAR 0040 +STARTCHAR @ ENCODING 64 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -1c -36 -6e -7a -7a -7a -7a -6e -30 -1e +78 +8c +8c +bc +ac +bc +80 +8c +78 00 00 ENDCHAR -STARTCHAR 0041 +STARTCHAR A ENCODING 65 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -7e -66 -66 -66 -66 -7e -66 -66 -66 +78 +cc +cc +cc +fc +cc +cc +cc +cc 00 00 ENDCHAR -STARTCHAR 0042 +STARTCHAR B ENCODING 66 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7c -66 -66 -64 -7c -66 -66 -66 -66 -7c +f8 +cc +cc +cc +f8 +cc +cc +cc +f8 00 00 ENDCHAR -STARTCHAR 0043 +STARTCHAR C ENCODING 67 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -60 -60 -60 -60 -66 -66 -3c +78 +cc +c0 +c0 +c0 +c0 +c0 +cc +78 00 00 ENDCHAR -STARTCHAR 0044 +STARTCHAR D ENCODING 68 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -78 -6c -66 -66 -66 -66 -66 -66 -6c -78 +f8 +cc +cc +cc +cc +cc +cc +cc +f8 00 00 ENDCHAR -STARTCHAR 0045 +STARTCHAR E ENCODING 69 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7e -60 -60 -60 -7c -60 -60 -60 -60 -7e +fc +c0 +c0 +c0 +f8 +c0 +c0 +c0 +fc 00 00 ENDCHAR -STARTCHAR 0046 +STARTCHAR F ENCODING 70 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7e -60 -60 -60 -7c -60 -60 -60 -60 -60 +fc +c0 +c0 +c0 +f8 +c0 +c0 +c0 +c0 00 00 ENDCHAR -STARTCHAR 0047 +STARTCHAR G ENCODING 71 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -60 -60 -6e -66 -66 -66 -3c +78 +cc +c0 +c0 +dc +cc +cc +cc +7c 00 00 ENDCHAR -STARTCHAR 0048 +STARTCHAR H ENCODING 72 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -66 -66 -66 -66 -7e -66 -66 -66 -66 -66 +cc +cc +cc +cc +fc +cc +cc +cc +cc 00 00 ENDCHAR -STARTCHAR 0049 +STARTCHAR I ENCODING 73 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7e -18 -18 -18 -18 -18 -18 -18 -18 -7e +fc +30 +30 +30 +30 +30 +30 +30 +fc 00 00 ENDCHAR -STARTCHAR 004a +STARTCHAR J ENCODING 74 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -06 -06 -06 -06 -06 -06 -06 -66 -6c -38 +0c +0c +0c +0c +0c +0c +0c +cc +78 00 00 ENDCHAR -STARTCHAR 004b +STARTCHAR K ENCODING 75 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -66 -6c -78 -70 -70 -78 -78 -6c -66 -66 +c4 +cc +d8 +f0 +e0 +f0 +d8 +cc +c4 00 00 ENDCHAR -STARTCHAR 004c +STARTCHAR L ENCODING 76 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -7e +c0 +c0 +c0 +c0 +c0 +c0 +c0 +c0 +fc 00 00 ENDCHAR -STARTCHAR 004d +STARTCHAR M ENCODING 77 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -42 -66 -66 -7e -7e -66 -66 -66 -66 -66 +84 +cc +fc +fc +cc +cc +cc +cc +cc 00 00 ENDCHAR -STARTCHAR 004e +STARTCHAR N ENCODING 78 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -66 -66 -76 -76 -76 -6e -6e -6e -66 -66 +cc +cc +ec +ec +fc +dc +dc +cc +cc 00 00 ENDCHAR -STARTCHAR 004f +STARTCHAR O ENCODING 79 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -66 -66 -66 -66 -66 -66 -3c +78 +cc +cc +cc +cc +cc +cc +cc +78 00 00 ENDCHAR -STARTCHAR 0050 +STARTCHAR P ENCODING 80 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7c -66 -66 -66 -66 -7c -60 -60 -60 -60 +f8 +cc +cc +cc +f8 +c0 +c0 +c0 +c0 00 00 ENDCHAR -STARTCHAR 0051 +STARTCHAR Q ENCODING 81 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -66 -66 -66 -76 -6e -66 -3c -06 -02 +78 +cc +cc +cc +cc +cc +ec +dc +78 +0c +00 ENDCHAR -STARTCHAR 0052 +STARTCHAR R ENCODING 82 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7c -66 -66 -66 -7c -6c -66 -66 -66 -66 +f8 +cc +cc +cc +f8 +f0 +d8 +cc +c4 00 00 ENDCHAR -STARTCHAR 0053 +STARTCHAR S ENCODING 83 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -30 -18 -18 +78 +cc +c0 +c0 +78 0c -66 -66 -3c +0c +cc +78 00 00 ENDCHAR -STARTCHAR 0054 +STARTCHAR T ENCODING 84 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7e -18 -18 -18 -18 -18 -18 -18 -18 -18 +fc +30 +30 +30 +30 +30 +30 +30 +30 00 00 ENDCHAR -STARTCHAR 0055 +STARTCHAR U ENCODING 85 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -66 -66 -66 -66 -66 -66 -66 -66 -66 -3c +cc +cc +cc +cc +cc +cc +cc +cc +78 00 00 ENDCHAR -STARTCHAR 0056 +STARTCHAR V ENCODING 86 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -66 -66 -66 -66 -66 -66 -66 -3c -3c -18 +cc +cc +cc +48 +48 +78 +30 +30 +30 00 00 ENDCHAR -STARTCHAR 0057 +STARTCHAR W ENCODING 87 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -66 -66 -66 -66 -66 -7e -7e -7e -7e -24 +cc +cc +cc +cc +cc +fc +fc +cc +84 00 00 ENDCHAR -STARTCHAR 0058 +STARTCHAR X ENCODING 88 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -66 -66 -3c -3c -18 -18 -3c -3c -66 -66 +84 +cc +48 +78 +30 +78 +48 +cc +84 00 00 ENDCHAR -STARTCHAR 0059 +STARTCHAR Y ENCODING 89 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -66 -66 -66 -3c -3c -18 -18 -18 -18 -18 +cc +cc +78 +78 +30 +30 +30 +30 +30 00 00 ENDCHAR -STARTCHAR 005a +STARTCHAR Z ENCODING 90 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7e -06 +fc 0c 0c 18 -18 -30 30 60 -7e +c0 +c0 +fc 00 00 ENDCHAR -STARTCHAR 005b +STARTCHAR [ ENCODING 91 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -3e -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -3e +00 +78 +60 +60 +60 +60 +60 +60 +60 +78 +00 +00 ENDCHAR -STARTCHAR 005c +STARTCHAR \ ENCODING 92 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -60 +00 +c0 +c0 60 60 30 -30 -18 18 18 0c 0c -06 -06 -06 +00 +00 ENDCHAR -STARTCHAR 005d +STARTCHAR ] ENCODING 93 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -7c -0c -0c -0c -0c -0c -0c -0c -0c -0c -0c -0c -7c +00 +78 +18 +18 +18 +18 +18 +18 +18 +78 +00 +00 ENDCHAR -STARTCHAR 005e +STARTCHAR ^ ENCODING 94 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -3c -66 -00 -00 00 00 +30 +78 +cc +84 00 00 00 @@ -1708,11 +1934,11 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 005f +STARTCHAR _ ENCODING 95 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -1724,24 +1950,22 @@ BITMAP 00 00 00 +fc +fc 00 -00 -7e -7e ENDCHAR -STARTCHAR 0060 +STARTCHAR ` ENCODING 96 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -1c +00 +00 +70 +70 +30 18 -18 -0c -00 -00 -00 00 00 00 @@ -1750,200 +1974,191 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 0061 +STARTCHAR a ENCODING 97 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -3c -66 -0e -36 -66 -66 -3e +78 +0c +7c +cc +cc +7c 00 00 ENDCHAR -STARTCHAR 0062 +STARTCHAR b ENCODING 98 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -60 -60 -60 -7c -66 -66 -66 -66 -66 -7c +c0 +c0 +c0 +f8 +cc +cc +cc +cc +f8 00 00 ENDCHAR -STARTCHAR 0063 +STARTCHAR c ENCODING 99 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -3c -66 -60 -60 -60 -66 -3c +78 +cc +c0 +c0 +cc +78 00 00 ENDCHAR -STARTCHAR 0064 +STARTCHAR d ENCODING 100 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -06 -06 -06 -3e -66 -66 -66 -66 -66 -3e +0c +0c +0c +7c +cc +cc +cc +cc +7c 00 00 ENDCHAR -STARTCHAR 0065 +STARTCHAR e ENCODING 101 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -3c -66 -66 -7e -60 -66 -3c +78 +cc +fc +c0 +cc +78 00 00 ENDCHAR -STARTCHAR 0066 +STARTCHAR f ENCODING 102 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -0c -1e -18 -18 -7e -18 -18 -18 -18 -18 +38 +6c +60 +60 +f0 +60 +60 +60 +60 00 00 ENDCHAR -STARTCHAR 0067 +STARTCHAR g ENCODING 103 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -3a -6e -6c -6c -38 -20 -7c -66 -3c +74 +cc +cc +78 +c0 +78 +cc +78 ENDCHAR -STARTCHAR 0068 +STARTCHAR h ENCODING 104 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -60 -60 -60 -7c -66 -66 -66 -66 -66 -66 +c0 +c0 +c0 +f8 +cc +cc +cc +cc +cc 00 00 ENDCHAR -STARTCHAR 0069 +STARTCHAR i ENCODING 105 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -18 +30 +30 00 -18 -18 -18 -18 -18 -18 -18 +70 +30 +30 +30 +30 +fc 00 00 ENDCHAR -STARTCHAR 006a +STARTCHAR j ENCODING 106 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -1956,421 +2171,400 @@ BITMAP 0c 0c 0c -0c -6c -38 +cc +78 ENDCHAR -STARTCHAR 006b +STARTCHAR k ENCODING 107 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -60 -60 -60 -64 -6c -78 -78 -6c -66 -62 +c0 +c0 +c0 +cc +d8 +f0 +f0 +d8 +cc 00 00 ENDCHAR -STARTCHAR 006c +STARTCHAR l ENCODING 108 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -00 -00 -ENDCHAR -STARTCHAR 006d -ENCODING 109 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -6c -7e -7e -7e -7e -7e -7e -00 -00 -ENDCHAR -STARTCHAR 006e -ENCODING 110 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -7c -66 -66 -66 -66 -66 -66 -00 -00 -ENDCHAR -STARTCHAR 006f -ENCODING 111 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3c -66 -66 -66 -66 -66 -3c -00 -00 -ENDCHAR -STARTCHAR 0070 -ENCODING 112 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -7c -66 -66 -66 -66 -66 -7c -60 -60 -ENDCHAR -STARTCHAR 0071 -ENCODING 113 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3e -66 -66 -66 -66 -66 -3e -06 -06 -ENDCHAR -STARTCHAR 0072 -ENCODING 114 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -7c -66 -66 -60 -60 -60 -60 -00 -00 -ENDCHAR -STARTCHAR 0073 -ENCODING 115 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -3c -66 +70 30 -18 -0c -66 -3c +30 +30 +30 +30 +30 +30 +fc 00 00 ENDCHAR -STARTCHAR 0074 +STARTCHAR m +ENCODING 109 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +d8 +fc +fc +cc +cc +cc +00 +00 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +f8 +cc +cc +cc +cc +cc +00 +00 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +78 +cc +cc +cc +cc +78 +00 +00 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +f8 +cc +cc +cc +f8 +c0 +c0 +c0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +7c +cc +cc +cc +7c +0c +0c +0c +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +f8 +cc +c0 +c0 +c0 +c0 +00 +00 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +78 +cc +60 +18 +cc +78 +00 +00 +ENDCHAR +STARTCHAR t ENCODING 116 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -18 -18 -18 -7e -18 -18 -18 -18 -18 -0e -00 -00 -ENDCHAR -STARTCHAR 0075 -ENCODING 117 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 -00 -00 -66 -66 -66 -66 -66 -66 -3e -00 -00 -ENDCHAR -STARTCHAR 0076 -ENCODING 118 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -66 -66 -66 -3c -3c -18 -18 -00 -00 -ENDCHAR -STARTCHAR 0077 -ENCODING 119 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -66 -66 -7e -7e -7e -7e -24 -00 -00 -ENDCHAR -STARTCHAR 0078 -ENCODING 120 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -66 -66 -3c -18 -3c -66 -66 -00 -00 -ENDCHAR -STARTCHAR 0079 -ENCODING 121 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -00 -00 -00 -00 -66 -66 -36 -36 -1c -1c -0c +60 +60 +f8 +60 +60 +60 6c 38 +00 +00 ENDCHAR -STARTCHAR 007a -ENCODING 122 -SWIDTH 480 0 +STARTCHAR u +ENCODING 117 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -7e -06 +cc +cc +cc +cc +cc +7c +00 +00 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +cc +cc +cc +78 +78 +30 +00 +00 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +cc +cc +cc +fc +fc +48 +00 +00 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +cc +cc +78 +78 +cc +cc +00 +00 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +cc +cc +cc +cc +7c +0c +cc +78 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +00 +00 +00 +fc 0c 18 +60 +c0 +fc +00 +00 +ENDCHAR +STARTCHAR { +ENCODING 123 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +38 +60 +60 30 60 -7e +30 +60 +60 +38 00 00 ENDCHAR -STARTCHAR 007b -ENCODING 123 -SWIDTH 480 0 +STARTCHAR | +ENCODING 124 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -0e -18 -18 -18 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +00 +00 +ENDCHAR +STARTCHAR } +ENCODING 125 +SWIDTH 570 0 +DWIDTH 7 0 +BBX 7 13 0 -2 +BITMAP +00 +00 +70 18 18 30 18 -18 -18 -18 -18 -0e -ENDCHAR -STARTCHAR 007c -ENCODING 124 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR 007d -ENCODING 125 -SWIDTH 480 0 -DWIDTH 7 0 -BBX 7 14 0 -2 -BITMAP -00 -70 -18 -18 -18 -18 -18 -0c -18 -18 -18 +30 18 18 70 +00 +00 ENDCHAR -STARTCHAR 007e +STARTCHAR ~ ENCODING 126 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -20 -7e -7e -04 00 +64 +fc +98 00 00 00 @@ -2380,11 +2574,11 @@ BITMAP 00 00 ENDCHAR -STARTCHAR 007f +STARTCHAR C177 ENCODING 127 -SWIDTH 480 0 +SWIDTH 570 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2399,13 +2593,12 @@ BITMAP 00 00 00 -00 ENDCHAR STARTCHAR 00a0 ENCODING 160 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2420,160 +2613,152 @@ BITMAP 00 00 00 -00 ENDCHAR STARTCHAR 00a1 ENCODING 161 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +30 +30 00 -18 -18 -00 -18 -18 -18 -18 -18 -18 -18 +30 +30 +30 +30 +30 +30 +30 00 00 ENDCHAR STARTCHAR 00a2 ENCODING 162 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 +10 +7c +d4 +d0 +d0 +d4 +7c +10 00 00 -18 -3e -5a -58 -58 -58 -5a -3e -18 00 ENDCHAR STARTCHAR 00a3 ENCODING 163 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -00 -1c -36 -30 -30 -78 -30 -30 -7c -36 +38 +6c +60 +60 +f8 +60 +60 +6c +b8 00 00 ENDCHAR STARTCHAR 00a4 ENCODING 164 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 -66 -3c -34 -2c -3c -66 -00 +cc +fc +48 +48 +fc +cc 00 00 00 ENDCHAR STARTCHAR 00a5 ENCODING 165 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -42 -66 -3c -7e -18 -18 -7e -18 -18 -18 +cc +cc +78 +78 +fc +30 +fc +30 +30 00 00 ENDCHAR STARTCHAR 00a6 ENCODING 166 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -18 -18 -18 -18 +30 +30 +30 +30 00 00 -18 -18 -18 -18 +30 +30 +30 +30 00 00 ENDCHAR STARTCHAR 00a7 ENCODING 167 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -3c -66 -30 -18 -3c -66 -3c -18 +78 +cc +c0 +78 +cc +cc +78 0c -66 -3c +cc +78 00 00 ENDCHAR STARTCHAR 00a8 ENCODING 168 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 6c @@ -2588,45 +2773,42 @@ BITMAP 00 00 00 -00 ENDCHAR STARTCHAR 00a9 ENCODING 169 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -3c -66 -7e -76 -76 -76 -76 -76 -7e -66 -3c +78 +cc +84 +b4 +e4 +e4 +b4 +84 +cc +78 00 00 ENDCHAR STARTCHAR 00aa ENCODING 170 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -1c -36 -1e -36 -36 -1e 00 -3e +78 +0c +7c +4c +7c 00 +7c 00 00 00 @@ -2634,62 +2816,59 @@ BITMAP ENDCHAR STARTCHAR 00ab ENCODING 171 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 +34 +68 +d0 +a0 +d0 +68 +34 00 00 -0e -1e -3c -78 -3c -1e -0e -00 00 ENDCHAR STARTCHAR 00ac ENCODING 172 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -00 -00 fc fc -0c -0c -0c +04 +04 +00 +00 00 00 ENDCHAR STARTCHAR 00ad ENCODING 173 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 +7c +7c 00 00 -f0 -f0 -00 00 00 00 @@ -2697,35 +2876,33 @@ f0 ENDCHAR STARTCHAR 00ae ENCODING 174 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -3c -66 -7e -76 -76 -7e -76 -76 -76 -66 -3c +78 +cc +84 +bc +ac +bc +b4 +ac +cc +78 00 00 ENDCHAR STARTCHAR 00af ENCODING 175 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -f0 -f0 +7c +7c 00 00 00 @@ -2739,17 +2916,16 @@ f0 ENDCHAR STARTCHAR 00b0 ENCODING 176 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -38 -6c -6c -38 -00 00 +78 +cc +cc +78 00 00 00 @@ -2760,39 +2936,37 @@ BITMAP ENDCHAR STARTCHAR 00b1 ENCODING 177 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 +30 +30 +fc +fc +30 +30 00 -00 -00 -00 -18 -18 -7e -18 -18 -7e +fc +fc 00 00 ENDCHAR STARTCHAR 00b2 ENCODING 178 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -38 -6c -0c -18 +e0 +b0 30 60 -7c +c0 +f0 00 00 00 @@ -2802,18 +2976,17 @@ BITMAP ENDCHAR STARTCHAR 00b3 ENCODING 179 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -38 -6c -0c -38 -0c -6c -38 +e0 +b0 +60 +30 +b0 +e0 00 00 00 @@ -2823,15 +2996,14 @@ BITMAP ENDCHAR STARTCHAR 00b4 ENCODING 180 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -0c 18 30 -60 +00 00 00 00 @@ -2844,60 +3016,57 @@ BITMAP ENDCHAR STARTCHAR 00b5 ENCODING 181 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 +cc +cc +cc +cc +cc +fc +80 00 -66 -66 -66 -66 -6e -7e -60 -60 ENDCHAR STARTCHAR 00b6 ENCODING 182 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3e -76 -76 -76 -76 -36 -16 -16 -16 -16 -16 -1e +7c +fc +f4 +f4 +f4 +74 +34 +34 +34 +00 +00 ENDCHAR STARTCHAR 00b7 ENCODING 183 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -18 -18 -00 +30 +30 00 00 00 @@ -2907,9 +3076,9 @@ BITMAP ENDCHAR STARTCHAR 00b8 ENCODING 184 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 @@ -2922,24 +3091,22 @@ BITMAP 00 00 00 -18 -18 30 +60 ENDCHAR STARTCHAR 00b9 ENCODING 185 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -30 -70 -30 -30 -30 -30 +60 +e0 +60 +60 +60 +f0 00 00 00 @@ -2949,19 +3116,18 @@ BITMAP ENDCHAR STARTCHAR 00ba ENCODING 186 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +38 +7c +44 +7c +38 00 -1c -36 -36 -1c -00 -3e -00 +7c 00 00 00 @@ -2970,1451 +3136,1382 @@ BITMAP ENDCHAR STARTCHAR 00bb ENCODING 187 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 +b0 +58 +2c +14 +2c +58 +b0 00 00 -70 -38 -1c -0e -1c -38 -70 -00 00 ENDCHAR STARTCHAR 00bc ENCODING 188 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -32 -76 +60 +e0 +60 +60 +64 +fc +1c 34 3c -3c -1a -36 -2e -6e -46 +0c 00 00 ENDCHAR STARTCHAR 00bd ENCODING 189 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -32 -76 -34 +60 +e0 +60 +60 +78 +ec +0c +18 +30 3c -3c -1c -3a -26 -6c -4e 00 00 ENDCHAR STARTCHAR 00be ENCODING 190 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -00 -62 -36 -74 +e0 +b0 +60 +30 +b4 +ec +1c +34 3c -78 -1e -36 -6e -4e -06 +0c 00 00 ENDCHAR STARTCHAR 00bf ENCODING 191 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +30 +30 +00 +30 +30 +60 +c0 +cc +cc +78 00 00 -0c -0c -00 -0c -0c -0c -0c -0c -66 -66 -3c ENDCHAR STARTCHAR 00c0 ENCODING 192 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -38 -1c 00 -3c -7e -66 -66 -66 -7e -66 -66 -66 +30 +18 +00 +30 +78 +cc +cc +fc +cc +cc 00 00 ENDCHAR STARTCHAR 00c1 ENCODING 193 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -1c -38 00 -3c -7e -66 -66 -66 -7e -66 -66 -66 +18 +30 +00 +30 +78 +cc +cc +fc +cc +cc 00 00 ENDCHAR STARTCHAR 00c2 ENCODING 194 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -3c 00 -3c -7e -66 -66 -66 -7e -66 -66 -66 +70 +d8 +00 +30 +78 +cc +cc +fc +cc +cc 00 00 ENDCHAR STARTCHAR 00c3 ENCODING 195 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -14 -28 00 -3c -7e -66 -66 -66 -7e -66 -66 -66 +68 +b0 +00 +30 +78 +cc +cc +fc +cc +cc 00 00 ENDCHAR STARTCHAR 00c4 ENCODING 196 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -24 -24 00 -3c -7e -66 -66 -66 -7e -66 -66 -66 +cc +cc +00 +30 +78 +cc +cc +fc +cc +cc 00 00 ENDCHAR STARTCHAR 00c5 ENCODING 197 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -18 00 -3c -7e -66 -66 -66 -7e -66 -66 -66 +78 +48 +78 +30 +78 +cc +cc +fc +cc +cc 00 00 ENDCHAR STARTCHAR 00c6 ENCODING 198 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -7e -d8 +7c +f8 d8 d8 dc f8 d8 d8 -d8 -de +dc 00 00 ENDCHAR STARTCHAR 00c7 ENCODING 199 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -3c -66 -66 -60 -60 -60 -60 -66 -66 -3c -18 +78 +cc +c0 +c0 +c0 +c0 +c0 +cc +78 30 +60 ENDCHAR STARTCHAR 00c8 ENCODING 200 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -38 -1c 00 -7e -60 -60 -60 -7c -60 -60 -60 -7e +30 +18 +00 +fc +c0 +c0 +f0 +c0 +c0 +fc 00 00 ENDCHAR STARTCHAR 00c9 ENCODING 201 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -1c -38 00 -7e -60 -60 -60 -7c -60 -60 -60 -7e +18 +30 +00 +fc +c0 +c0 +f0 +c0 +c0 +fc 00 00 ENDCHAR STARTCHAR 00ca ENCODING 202 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -3c 00 -7e -60 -60 -60 -7c -60 -60 -60 -7e +70 +d8 +00 +fc +c0 +c0 +f0 +c0 +c0 +fc 00 00 ENDCHAR STARTCHAR 00cb ENCODING 203 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -24 -24 00 -7e -60 -60 -60 -7c -60 -60 -60 -7e +cc +cc +00 +fc +c0 +c0 +f0 +c0 +c0 +fc 00 00 ENDCHAR STARTCHAR 00cc ENCODING 204 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -38 -1c 00 -7e +30 18 -18 -18 -18 -18 -18 -18 -7e +00 +fc +30 +30 +30 +30 +30 +fc 00 00 ENDCHAR STARTCHAR 00cd ENCODING 205 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -1c -38 00 -7e 18 -18 -18 -18 -18 -18 -18 -7e +30 +00 +fc +30 +30 +30 +30 +30 +fc 00 00 ENDCHAR STARTCHAR 00ce ENCODING 206 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -3c 00 -7e -18 -18 -18 -18 -18 -18 -18 -7e +70 +d8 +00 +fc +30 +30 +30 +30 +30 +fc 00 00 ENDCHAR STARTCHAR 00cf ENCODING 207 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -24 -24 00 -7e -18 -18 -18 -18 -18 -18 -18 -7e +cc +cc +00 +fc +30 +30 +30 +30 +30 +fc 00 00 ENDCHAR STARTCHAR 00d0 ENCODING 208 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -78 +f8 6c -66 -66 -fe -66 -66 -66 6c -78 +6c +ec +6c +6c +6c +f8 00 00 ENDCHAR STARTCHAR 00d1 ENCODING 209 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -14 -28 00 -66 -76 -76 -76 -6e -6e -6e -66 -66 +68 +b0 +00 +cc +cc +ec +fc +dc +cc +cc 00 00 ENDCHAR STARTCHAR 00d2 ENCODING 210 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -38 -1c 00 -3c -66 -66 -66 -66 -66 -66 -66 -3c +30 +18 +00 +78 +cc +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00d3 ENCODING 211 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -1c -38 00 -3c -66 -66 -66 -66 -66 -66 -66 -3c +18 +30 +00 +78 +cc +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00d4 ENCODING 212 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -3c 00 -3c -66 -66 -66 -66 -66 -66 -66 -3c +70 +d8 +00 +78 +cc +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00d5 ENCODING 213 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -14 -28 00 -3c -66 -66 -66 -66 -66 -66 -66 -3c +68 +b0 +00 +78 +cc +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00d6 ENCODING 214 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -24 -24 00 -3c -66 -66 -66 -66 -66 -66 -66 -3c +cc +cc +00 +78 +cc +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00d7 ENCODING 215 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -c6 -6c -38 -38 -6c -c6 -82 +cc +78 +30 +78 +cc +00 00 00 ENDCHAR STARTCHAR 00d8 ENCODING 216 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -02 -02 -3c -6e -6e -6e -6e -76 -76 -76 -76 -3c -40 -40 +00 +00 +04 +78 +dc +dc +dc +ec +ec +ec +78 +80 +00 ENDCHAR STARTCHAR 00d9 ENCODING 217 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -38 -1c 00 -66 -66 -66 -66 -66 -66 -66 -66 -3c +30 +18 +00 +cc +cc +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00da ENCODING 218 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -1c -38 00 -66 -66 -66 -66 -66 -66 -66 -66 -3c +18 +30 +00 +cc +cc +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00db ENCODING 219 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -18 -3c 00 -66 -66 -66 -66 -66 -66 -66 -66 -3c +70 +d8 +00 +cc +cc +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00dc ENCODING 220 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -24 -24 00 -66 -66 -66 -66 -66 -66 -66 -66 -3c +cc +cc +00 +cc +cc +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00dd ENCODING 221 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP -1c -38 00 -66 -66 -66 -3c -3c -3c -18 -18 18 +30 +00 +cc +48 +78 +30 +30 +30 +30 00 00 ENDCHAR STARTCHAR 00de ENCODING 222 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -60 -60 -7c -66 -66 -66 -66 -7c -60 -60 +c0 +f8 +cc +cc +cc +f8 +c0 +c0 +c0 00 00 ENDCHAR STARTCHAR 00df ENCODING 223 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -1c -36 -36 -36 -3c -36 -36 -36 -36 -7c 00 +78 +cc +cc +f8 +cc +cc +cc +f8 +80 00 ENDCHAR STARTCHAR 00e0 ENCODING 224 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 30 18 -0c 00 -3c -66 -1e -36 -66 -66 -3e +00 +78 +0c +7c +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00e1 ENCODING 225 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -0c 18 30 00 -3c -66 -1e -36 -66 -66 -3e +00 +78 +0c +7c +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00e2 ENCODING 226 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +70 +d8 00 -18 -3c 00 -3c -66 -1e -36 -66 -66 -3e +78 +0c +7c +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00e3 ENCODING 227 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +68 +b0 00 -14 -28 00 -3c -66 -1e -36 -66 -66 -3e +78 +0c +7c +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00e4 ENCODING 228 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +6c +6c 00 -24 -24 00 -3c -66 -1e -36 -66 -66 -3e +78 +0c +7c +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00e5 ENCODING 229 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -18 -3c -18 +38 +28 +38 00 -3c -66 -1e -36 -66 -66 -3e +78 +0c +7c +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00e6 ENCODING 230 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 +78 +34 7c -da -3a -5e -d8 -de -7c +b0 +b4 +68 00 00 ENDCHAR STARTCHAR 00e7 ENCODING 231 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 00 00 -3c -66 -60 -60 -60 -66 -3c -18 +78 +cc +c0 +c0 +cc +78 30 +60 ENDCHAR STARTCHAR 00e8 ENCODING 232 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 30 18 -0c 00 -3c -66 -66 -7e -60 -66 -3c +00 +78 +cc +fc +c0 +cc +78 00 00 ENDCHAR STARTCHAR 00e9 ENCODING 233 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -0c 18 30 00 -3c -66 -66 -7e -60 -66 -3c +00 +78 +cc +fc +c0 +cc +78 00 00 ENDCHAR STARTCHAR 00ea ENCODING 234 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +70 +d8 00 -18 -3c 00 -3c -66 -66 -7e -60 -66 -3c +78 +cc +fc +c0 +cc +78 00 00 ENDCHAR STARTCHAR 00eb ENCODING 235 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +6c +6c 00 -24 -24 00 -3c -66 -66 -7e -60 -66 -3c +78 +cc +fc +c0 +cc +78 00 00 ENDCHAR STARTCHAR 00ec ENCODING 236 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 30 18 -0c 00 -18 -18 -18 -18 -18 -18 -18 +00 +70 +30 +30 +30 +30 +78 00 00 ENDCHAR STARTCHAR 00ed ENCODING 237 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -0c 18 30 00 -18 -18 -18 -18 -18 -18 -18 +00 +70 +30 +30 +30 +30 +78 00 00 ENDCHAR STARTCHAR 00ee ENCODING 238 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +70 +d8 00 -18 -3c 00 -18 -18 -18 -18 -18 -18 -18 +70 +30 +30 +30 +30 +78 00 00 ENDCHAR STARTCHAR 00ef ENCODING 239 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +6c +6c 00 -24 -24 00 -18 -18 -18 -18 -18 -18 -18 +70 +30 +30 +30 +30 +78 00 00 ENDCHAR STARTCHAR 00f0 ENCODING 240 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -28 -10 -2c -0c -3c -6c -6c -6c -6c -6c -38 +48 +30 +30 +50 +78 +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00f1 ENCODING 241 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +68 +b0 00 -14 -28 00 -7c -66 -66 -66 -66 -66 -66 +f8 +ec +cc +cc +cc +cc 00 00 ENDCHAR STARTCHAR 00f2 ENCODING 242 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 30 18 -0c 00 -3c -66 -66 -66 -66 -66 -3c +00 +78 +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00f3 ENCODING 243 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -0c 18 30 00 -3c -66 -66 -66 -66 -66 -3c +00 +78 +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00f4 ENCODING 244 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +70 +d8 00 -18 -3c 00 -3c -66 -66 -66 -66 -66 -3c +78 +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00f5 ENCODING 245 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +68 +b0 00 -14 -28 00 -3c -66 -66 -66 -66 -66 -3c +78 +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00f6 ENCODING 246 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +6c +6c 00 -24 -24 00 -3c -66 -66 -66 -66 -66 -3c +78 +cc +cc +cc +cc +78 00 00 ENDCHAR STARTCHAR 00f7 ENCODING 247 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 -00 -00 -00 -00 +30 30 00 fc 00 30 +30 +00 00 00 ENDCHAR STARTCHAR 00f8 ENCODING 248 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 00 -02 04 -3c -6e -6e -76 -76 -66 -3c -40 -40 +78 +cc +dc +cc +ec +cc +78 +80 +00 ENDCHAR STARTCHAR 00f9 ENCODING 249 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -20 30 18 -08 -66 -66 -66 -66 -66 -66 -3e +00 +00 +cc +cc +cc +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00fa ENCODING 250 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -04 -0c 18 -10 -66 -66 -66 -66 -66 -66 -3e +30 +00 +00 +cc +cc +cc +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00fb ENCODING 251 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +70 +d8 00 -18 -3c 00 -66 -66 -66 -66 -66 -66 -3e +cc +cc +cc +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00fc ENCODING 252 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +6c +6c 00 -24 -24 00 -66 -66 -66 -66 -66 -66 -3e +cc +cc +cc +cc +dc +7c 00 00 ENDCHAR STARTCHAR 00fd ENCODING 253 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 -04 -0c 18 -10 -66 -66 -66 -3c -1c -1c -18 -78 30 +00 +00 +cc +cc +cc +dc +7c +0c +cc +78 ENDCHAR STARTCHAR 00fe ENCODING 254 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 00 -60 -60 -60 -7c -66 -66 -66 -66 -66 -7c -60 -60 +00 +c0 +c0 +f8 +ec +cc +cc +ec +f8 +c0 +c0 ENDCHAR STARTCHAR 00ff ENCODING 255 -SWIDTH 480 0 +SWIDTH 666 0 DWIDTH 7 0 -BBX 7 14 0 -2 +BBX 7 13 0 -2 BITMAP 00 +6c +6c 00 -24 -24 00 -66 -66 -66 -3c -1c -1c -18 +cc +cc +cc +dc +7c +0c +cc 78 -30 ENDCHAR ENDFONT diff --git a/src/default.c b/src/default.c index 44e4c4d..baeeb67 100644 --- a/src/default.c +++ b/src/default.c @@ -1,18 +1,38 @@ #include +// #define USE_CATPPUCCIN + +#ifdef USE_CATPPUCCIN +const char* MwDefaultBackground = "#eff1f5"; +const char* MwDefaultForeground = "#4c4f69"; +const char* MwDefaultSubBackground = "#9ca0b0"; +const char* MwDefaultSubForeground = "#6c6f85"; +const char* MwDefaultTitleBackground = "#bcc0cc"; +const char* MwDefaultTitleForeground = "#5c5f77"; +#else const char* MwDefaultBackground = "#d2d2d2"; const char* MwDefaultForeground = "#000"; const char* MwDefaultSubBackground = "#fff"; const char* MwDefaultSubForeground = "#000"; const char* MwDefaultTitleBackground = "#008"; const char* MwDefaultTitleForeground = "#fff"; +#endif +#ifdef USE_CATPPUCCIN +const char* MwDefaultDarkBackground = "#1e1e2e"; +const char* MwDefaultDarkForeground = "#cdd6f4"; +const char* MwDefaultDarkSubBackground = "#313244"; +const char* MwDefaultDarkSubForeground = "#a6adc8"; +const char* MwDefaultDarkTitleBackground = "#45475a"; +const char* MwDefaultDarkTitleForeground = "#bac2de"; +#else const char* MwDefaultDarkBackground = "#333"; const char* MwDefaultDarkForeground = "#ddd"; const char* MwDefaultDarkSubBackground = "#333"; const char* MwDefaultDarkSubForeground = "#ddd"; const char* MwDefaultDarkTitleBackground = "#008"; const char* MwDefaultDarkTitleForeground = "#fff"; +#endif const int MwDefaultShadow = -32; diff --git a/src/text/font/boldfont.c b/src/text/font/boldfont.c index c63be2c..b021ada 100644 --- a/src/text/font/boldfont.c +++ b/src/text/font/boldfont.c @@ -5,260 +5,260 @@ * "Public domain font. Share and enjoy." */ MwFont MwBoldFontData[] = { - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0 */ - {0, 12, {0, 0, 12, 12, 30, 30, 63, 63, 30, 30, 12, 12, 0, 0}}, /* 1 */ - {0, 12, {59, 119, 110, 93, 59, 119, 110, 93, 59, 119, 110, 93, 59, 119}}, /* 2 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 3 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 4 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 5 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 6 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 7 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 8 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 9 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 10 */ - {0, 12, {12, 12, 12, 12, 12, 12, 124, 124, 0, 0, 0, 0, 0, 0}}, /* 11 */ - {0, 12, {0, 0, 0, 0, 0, 0, 124, 124, 12, 12, 12, 12, 12, 12}}, /* 12 */ - {0, 12, {0, 0, 0, 0, 0, 0, 15, 15, 12, 12, 12, 12, 12, 12}}, /* 13 */ - {0, 12, {12, 12, 12, 12, 12, 12, 15, 15, 0, 0, 0, 0, 0, 0}}, /* 14 */ - {0, 12, {12, 12, 12, 12, 12, 12, 127, 127, 12, 12, 12, 12, 12, 12}}, /* 15 */ - {0, 12, {127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 16 */ - {0, 12, {0, 0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 17 */ - {0, 12, {0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0, 0}}, /* 18 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0}}, /* 19 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 127}}, /* 20 */ - {0, 12, {12, 12, 12, 12, 12, 12, 15, 15, 12, 12, 12, 12, 12, 12}}, /* 21 */ - {0, 12, {12, 12, 12, 12, 12, 12, 124, 124, 12, 12, 12, 12, 12, 12}}, /* 22 */ - {0, 12, {12, 12, 12, 12, 12, 12, 127, 127, 0, 0, 0, 0, 0, 0}}, /* 23 */ - {0, 12, {0, 0, 0, 0, 0, 0, 127, 127, 12, 12, 12, 12, 12, 12}}, /* 24 */ - {0, 12, {12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}}, /* 25 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 26 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 27 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 28 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 29 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 30 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 31 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 32 */ - {0, 12, {0, 0, 12, 12, 12, 12, 12, 12, 12, 0, 12, 12, 0, 0}}, /* 33 */ - {0, 12, {63, 27, 27, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 34 */ - {0, 12, {0, 0, 15, 15, 15, 63, 30, 30, 63, 60, 60, 60, 0, 0}}, /* 35 */ - {0, 12, {0, 0, 12, 30, 45, 45, 28, 14, 13, 45, 45, 30, 12, 0}}, /* 36 */ - {0, 12, {0, 0, 27, 55, 54, 28, 4, 8, 14, 27, 59, 54, 0, 0}}, /* 37 */ - {0, 12, {0, 0, 14, 27, 27, 27, 14, 27, 55, 54, 54, 27, 0, 0}}, /* 38 */ - {0, 12, {28, 12, 12, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 39 */ - {0, 12, {0, 3, 6, 12, 12, 24, 24, 24, 24, 24, 12, 12, 6, 3}}, /* 40 */ - {0, 12, {0, 48, 24, 12, 12, 6, 6, 6, 6, 6, 12, 12, 24, 48}}, /* 41 */ - {0, 12, {0, 0, 0, 45, 45, 30, 12, 12, 30, 45, 45, 0, 0, 0}}, /* 42 */ - {0, 12, {0, 0, 0, 0, 12, 12, 12, 63, 12, 12, 12, 0, 0, 0}}, /* 43 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 12, 12, 24}}, /* 44 */ - {0, 12, {0, 0, 0, 0, 0, 0, 63, 63, 0, 0, 0, 0, 0, 0}}, /* 45 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0}}, /* 46 */ - {0, 12, {0, 3, 3, 3, 6, 6, 12, 12, 12, 24, 24, 48, 48, 48}}, /* 47 */ - {0, 12, {0, 0, 30, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 48 */ - {0, 12, {0, 0, 12, 28, 60, 12, 12, 12, 12, 12, 12, 63, 0, 0}}, /* 49 */ - {0, 12, {0, 0, 30, 51, 51, 3, 6, 6, 12, 24, 48, 63, 0, 0}}, /* 50 */ - {0, 12, {0, 0, 30, 51, 51, 3, 14, 3, 3, 51, 51, 30, 0, 0}}, /* 51 */ - {0, 12, {0, 0, 2, 6, 6, 14, 30, 22, 54, 63, 2, 2, 0, 0}}, /* 52 */ - {0, 12, {0, 0, 63, 48, 48, 62, 51, 3, 3, 51, 51, 30, 0, 0}}, /* 53 */ - {0, 12, {0, 0, 14, 27, 51, 48, 62, 51, 51, 51, 51, 30, 0, 0}}, /* 54 */ - {0, 12, {0, 0, 63, 51, 54, 6, 12, 12, 12, 12, 12, 12, 0, 0}}, /* 55 */ - {0, 12, {0, 0, 30, 51, 51, 30, 12, 30, 51, 51, 51, 30, 0, 0}}, /* 56 */ - {0, 12, {0, 0, 30, 51, 51, 51, 51, 31, 3, 51, 54, 28, 0, 0}}, /* 57 */ - {0, 12, {0, 0, 0, 0, 12, 12, 0, 0, 0, 12, 12, 0, 0, 0}}, /* 58 */ - {0, 12, {0, 0, 0, 0, 12, 12, 0, 0, 0, 28, 12, 12, 24, 0}}, /* 59 */ - {0, 12, {0, 0, 0, 3, 6, 12, 24, 48, 24, 12, 6, 3, 0, 0}}, /* 60 */ - {0, 12, {0, 0, 0, 0, 63, 63, 0, 63, 63, 0, 0, 0, 0, 0}}, /* 61 */ - {0, 12, {0, 0, 0, 48, 24, 12, 6, 3, 6, 12, 24, 48, 0, 0}}, /* 62 */ - {0, 12, {0, 0, 30, 51, 51, 6, 12, 12, 12, 0, 12, 12, 0, 0}}, /* 63 */ - {0, 12, {0, 0, 14, 27, 55, 61, 61, 61, 61, 55, 24, 15, 0, 0}}, /* 64 */ - {0, 12, {0, 0, 30, 63, 51, 51, 51, 51, 63, 51, 51, 51, 0, 0}}, /* 65 */ - {0, 12, {0, 0, 62, 51, 51, 50, 62, 51, 51, 51, 51, 62, 0, 0}}, /* 66 */ - {0, 12, {0, 0, 30, 51, 51, 48, 48, 48, 48, 51, 51, 30, 0, 0}}, /* 67 */ - {0, 12, {0, 0, 60, 54, 51, 51, 51, 51, 51, 51, 54, 60, 0, 0}}, /* 68 */ - {0, 12, {0, 0, 63, 48, 48, 48, 62, 48, 48, 48, 48, 63, 0, 0}}, /* 69 */ - {0, 12, {0, 0, 63, 48, 48, 48, 62, 48, 48, 48, 48, 48, 0, 0}}, /* 70 */ - {0, 12, {0, 0, 30, 51, 51, 48, 48, 55, 51, 51, 51, 30, 0, 0}}, /* 71 */ - {0, 12, {0, 0, 51, 51, 51, 51, 63, 51, 51, 51, 51, 51, 0, 0}}, /* 72 */ - {0, 12, {0, 0, 63, 12, 12, 12, 12, 12, 12, 12, 12, 63, 0, 0}}, /* 73 */ - {0, 12, {0, 0, 3, 3, 3, 3, 3, 3, 3, 51, 54, 28, 0, 0}}, /* 74 */ - {0, 12, {0, 0, 51, 54, 60, 56, 56, 60, 60, 54, 51, 51, 0, 0}}, /* 75 */ - {0, 12, {0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 63, 0, 0}}, /* 76 */ - {0, 12, {0, 0, 33, 51, 51, 63, 63, 51, 51, 51, 51, 51, 0, 0}}, /* 77 */ - {0, 12, {0, 0, 51, 51, 59, 59, 59, 55, 55, 55, 51, 51, 0, 0}}, /* 78 */ - {0, 12, {0, 0, 30, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 79 */ - {0, 12, {0, 0, 62, 51, 51, 51, 51, 62, 48, 48, 48, 48, 0, 0}}, /* 80 */ - {0, 12, {0, 0, 30, 51, 51, 51, 51, 51, 59, 55, 51, 30, 3, 1}}, /* 81 */ - {0, 12, {0, 0, 62, 51, 51, 51, 62, 54, 51, 51, 51, 51, 0, 0}}, /* 82 */ - {0, 12, {0, 0, 30, 51, 51, 24, 12, 12, 6, 51, 51, 30, 0, 0}}, /* 83 */ - {0, 12, {0, 0, 63, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0}}, /* 84 */ - {0, 12, {0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 85 */ - {0, 12, {0, 0, 51, 51, 51, 51, 51, 51, 51, 30, 30, 12, 0, 0}}, /* 86 */ - {0, 12, {0, 0, 51, 51, 51, 51, 51, 63, 63, 63, 63, 18, 0, 0}}, /* 87 */ - {0, 12, {0, 0, 51, 51, 30, 30, 12, 12, 30, 30, 51, 51, 0, 0}}, /* 88 */ - {0, 12, {0, 0, 51, 51, 51, 30, 30, 12, 12, 12, 12, 12, 0, 0}}, /* 89 */ - {0, 12, {0, 0, 63, 3, 6, 6, 12, 12, 24, 24, 48, 63, 0, 0}}, /* 90 */ - {0, 12, {0, 31, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 31}}, /* 91 */ - {0, 12, {0, 48, 48, 48, 24, 24, 12, 12, 12, 6, 6, 3, 3, 3}}, /* 92 */ - {0, 12, {0, 62, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 62}}, /* 93 */ - {0, 12, {12, 30, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 94 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 63}}, /* 95 */ - {0, 12, {14, 12, 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 96 */ - {0, 12, {0, 0, 0, 0, 0, 30, 51, 7, 27, 51, 51, 31, 0, 0}}, /* 97 */ - {0, 12, {0, 0, 48, 48, 48, 62, 51, 51, 51, 51, 51, 62, 0, 0}}, /* 98 */ - {0, 12, {0, 0, 0, 0, 0, 30, 51, 48, 48, 48, 51, 30, 0, 0}}, /* 99 */ - {0, 12, {0, 0, 3, 3, 3, 31, 51, 51, 51, 51, 51, 31, 0, 0}}, /* 100 */ - {0, 12, {0, 0, 0, 0, 0, 30, 51, 51, 63, 48, 51, 30, 0, 0}}, /* 101 */ - {0, 12, {0, 0, 6, 15, 12, 12, 63, 12, 12, 12, 12, 12, 0, 0}}, /* 102 */ - {0, 12, {0, 0, 0, 0, 0, 29, 55, 54, 54, 28, 16, 62, 51, 30}}, /* 103 */ - {0, 12, {0, 0, 48, 48, 48, 62, 51, 51, 51, 51, 51, 51, 0, 0}}, /* 104 */ - {0, 12, {0, 0, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 0, 0}}, /* 105 */ - {0, 12, {0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 54, 28}}, /* 106 */ - {0, 12, {0, 0, 48, 48, 48, 50, 54, 60, 60, 54, 51, 49, 0, 0}}, /* 107 */ - {0, 12, {0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0}}, /* 108 */ - {0, 12, {0, 0, 0, 0, 0, 54, 63, 63, 63, 63, 63, 63, 0, 0}}, /* 109 */ - {0, 12, {0, 0, 0, 0, 0, 62, 51, 51, 51, 51, 51, 51, 0, 0}}, /* 110 */ - {0, 12, {0, 0, 0, 0, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 111 */ - {0, 12, {0, 0, 0, 0, 0, 62, 51, 51, 51, 51, 51, 62, 48, 48}}, /* 112 */ - {0, 12, {0, 0, 0, 0, 0, 31, 51, 51, 51, 51, 51, 31, 3, 3}}, /* 113 */ - {0, 12, {0, 0, 0, 0, 0, 62, 51, 51, 48, 48, 48, 48, 0, 0}}, /* 114 */ - {0, 12, {0, 0, 0, 0, 0, 30, 51, 24, 12, 6, 51, 30, 0, 0}}, /* 115 */ - {0, 12, {0, 0, 12, 12, 12, 63, 12, 12, 12, 12, 12, 7, 0, 0}}, /* 116 */ - {0, 12, {0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 51, 31, 0, 0}}, /* 117 */ - {0, 12, {0, 0, 0, 0, 0, 51, 51, 51, 30, 30, 12, 12, 0, 0}}, /* 118 */ - {0, 12, {0, 0, 0, 0, 0, 51, 51, 63, 63, 63, 63, 18, 0, 0}}, /* 119 */ - {0, 12, {0, 0, 0, 0, 0, 51, 51, 30, 12, 30, 51, 51, 0, 0}}, /* 120 */ - {0, 12, {0, 0, 0, 0, 0, 51, 51, 27, 27, 14, 14, 6, 54, 28}}, /* 121 */ - {0, 12, {0, 0, 0, 0, 0, 63, 3, 6, 12, 24, 48, 63, 0, 0}}, /* 122 */ - {0, 12, {0, 7, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 7}}, /* 123 */ - {0, 12, {0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}}, /* 124 */ - {0, 12, {0, 56, 12, 12, 12, 12, 12, 6, 12, 12, 12, 12, 12, 56}}, /* 125 */ - {0, 12, {0, 16, 63, 63, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 126 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 127 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 128 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 129 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 130 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 131 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 132 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 133 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 134 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 135 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 136 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 137 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 138 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 139 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 140 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 141 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 142 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 143 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 144 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 145 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 146 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 147 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 148 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 149 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 150 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 151 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 152 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 153 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 154 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 155 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 156 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 157 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 158 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 159 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 160 */ - {0, 12, {0, 0, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 0, 0}}, /* 161 */ - {0, 12, {0, 0, 0, 0, 12, 31, 45, 44, 44, 44, 45, 31, 12, 0}}, /* 162 */ - {0, 12, {0, 0, 0, 14, 27, 24, 24, 60, 24, 24, 62, 27, 0, 0}}, /* 163 */ - {0, 12, {0, 0, 0, 0, 51, 30, 26, 22, 30, 51, 0, 0, 0, 0}}, /* 164 */ - {0, 12, {0, 0, 33, 51, 30, 63, 12, 12, 63, 12, 12, 12, 0, 0}}, /* 165 */ - {0, 12, {0, 0, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12, 0, 0}}, /* 166 */ - {0, 12, {0, 30, 51, 24, 12, 30, 51, 30, 12, 6, 51, 30, 0, 0}}, /* 167 */ - {0, 12, {0, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 168 */ - {0, 12, {0, 30, 51, 63, 59, 59, 59, 59, 59, 63, 51, 30, 0, 0}}, /* 169 */ - {0, 12, {0, 14, 27, 15, 27, 27, 15, 0, 31, 0, 0, 0, 0, 0}}, /* 170 */ - {0, 12, {0, 0, 0, 0, 0, 7, 15, 30, 60, 30, 15, 7, 0, 0}}, /* 171 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 126, 126, 6, 6, 6, 0, 0}}, /* 172 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 120, 120, 0, 0, 0, 0, 0}}, /* 173 */ - {0, 12, {0, 30, 51, 63, 59, 59, 63, 59, 59, 59, 51, 30, 0, 0}}, /* 174 */ - {0, 12, {0, 0, 120, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 175 */ - {0, 12, {0, 28, 54, 54, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 176 */ - {0, 12, {0, 0, 0, 0, 0, 0, 12, 12, 63, 12, 12, 63, 0, 0}}, /* 177 */ - {0, 12, {0, 28, 54, 6, 12, 24, 48, 62, 0, 0, 0, 0, 0, 0}}, /* 178 */ - {0, 12, {0, 28, 54, 6, 28, 6, 54, 28, 0, 0, 0, 0, 0, 0}}, /* 179 */ - {0, 12, {0, 6, 12, 24, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 180 */ - {0, 12, {0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 55, 63, 48, 48}}, /* 181 */ - {0, 12, {0, 0, 31, 59, 59, 59, 59, 27, 11, 11, 11, 11, 11, 15}}, /* 182 */ - {0, 12, {0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0}}, /* 183 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 24}}, /* 184 */ - {0, 12, {0, 0, 24, 56, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0}}, /* 185 */ - {0, 12, {0, 0, 14, 27, 27, 14, 0, 31, 0, 0, 0, 0, 0, 0}}, /* 186 */ - {0, 12, {0, 0, 0, 0, 0, 56, 28, 14, 7, 14, 28, 56, 0, 0}}, /* 187 */ - {0, 12, {0, 0, 25, 59, 26, 30, 30, 13, 27, 23, 55, 35, 0, 0}}, /* 188 */ - {0, 12, {0, 0, 25, 59, 26, 30, 30, 14, 29, 19, 54, 39, 0, 0}}, /* 189 */ - {0, 12, {0, 0, 49, 27, 58, 30, 60, 15, 27, 55, 39, 3, 0, 0}}, /* 190 */ - {0, 12, {0, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 51, 51, 30}}, /* 191 */ - {0, 12, {28, 14, 0, 30, 63, 51, 51, 51, 63, 51, 51, 51, 0, 0}}, /* 192 */ - {0, 12, {14, 28, 0, 30, 63, 51, 51, 51, 63, 51, 51, 51, 0, 0}}, /* 193 */ - {0, 12, {12, 30, 0, 30, 63, 51, 51, 51, 63, 51, 51, 51, 0, 0}}, /* 194 */ - {0, 12, {10, 20, 0, 30, 63, 51, 51, 51, 63, 51, 51, 51, 0, 0}}, /* 195 */ - {0, 12, {18, 18, 0, 30, 63, 51, 51, 51, 63, 51, 51, 51, 0, 0}}, /* 196 */ - {0, 12, {12, 12, 0, 30, 63, 51, 51, 51, 63, 51, 51, 51, 0, 0}}, /* 197 */ - {0, 12, {0, 0, 63, 108, 108, 108, 110, 124, 108, 108, 108, 111, 0, 0}}, /* 198 */ - {0, 12, {0, 0, 30, 51, 51, 48, 48, 48, 48, 51, 51, 30, 12, 24}}, /* 199 */ - {0, 12, {28, 14, 0, 63, 48, 48, 48, 62, 48, 48, 48, 63, 0, 0}}, /* 200 */ - {0, 12, {14, 28, 0, 63, 48, 48, 48, 62, 48, 48, 48, 63, 0, 0}}, /* 201 */ - {0, 12, {12, 30, 0, 63, 48, 48, 48, 62, 48, 48, 48, 63, 0, 0}}, /* 202 */ - {0, 12, {18, 18, 0, 63, 48, 48, 48, 62, 48, 48, 48, 63, 0, 0}}, /* 203 */ - {0, 12, {28, 14, 0, 63, 12, 12, 12, 12, 12, 12, 12, 63, 0, 0}}, /* 204 */ - {0, 12, {14, 28, 0, 63, 12, 12, 12, 12, 12, 12, 12, 63, 0, 0}}, /* 205 */ - {0, 12, {12, 30, 0, 63, 12, 12, 12, 12, 12, 12, 12, 63, 0, 0}}, /* 206 */ - {0, 12, {18, 18, 0, 63, 12, 12, 12, 12, 12, 12, 12, 63, 0, 0}}, /* 207 */ - {0, 12, {0, 0, 60, 54, 51, 51, 127, 51, 51, 51, 54, 60, 0, 0}}, /* 208 */ - {0, 12, {10, 20, 0, 51, 59, 59, 59, 55, 55, 55, 51, 51, 0, 0}}, /* 209 */ - {0, 12, {28, 14, 0, 30, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 210 */ - {0, 12, {14, 28, 0, 30, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 211 */ - {0, 12, {12, 30, 0, 30, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 212 */ - {0, 12, {10, 20, 0, 30, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 213 */ - {0, 12, {18, 18, 0, 30, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 214 */ - {0, 12, {0, 0, 0, 0, 0, 99, 54, 28, 28, 54, 99, 65, 0, 0}}, /* 215 */ - {0, 12, {1, 1, 30, 55, 55, 55, 55, 59, 59, 59, 59, 30, 32, 32}}, /* 216 */ - {0, 12, {28, 14, 0, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 217 */ - {0, 12, {14, 28, 0, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 218 */ - {0, 12, {12, 30, 0, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 219 */ - {0, 12, {18, 18, 0, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 220 */ - {0, 12, {14, 28, 0, 51, 51, 51, 30, 30, 30, 12, 12, 12, 0, 0}}, /* 221 */ - {0, 12, {0, 0, 48, 48, 62, 51, 51, 51, 51, 62, 48, 48, 0, 0}}, /* 222 */ - {0, 12, {0, 0, 14, 27, 27, 27, 30, 27, 27, 27, 27, 62, 0, 0}}, /* 223 */ - {0, 12, {0, 24, 12, 6, 0, 30, 51, 15, 27, 51, 51, 31, 0, 0}}, /* 224 */ - {0, 12, {0, 6, 12, 24, 0, 30, 51, 15, 27, 51, 51, 31, 0, 0}}, /* 225 */ - {0, 12, {0, 0, 12, 30, 0, 30, 51, 15, 27, 51, 51, 31, 0, 0}}, /* 226 */ - {0, 12, {0, 0, 10, 20, 0, 30, 51, 15, 27, 51, 51, 31, 0, 0}}, /* 227 */ - {0, 12, {0, 0, 18, 18, 0, 30, 51, 15, 27, 51, 51, 31, 0, 0}}, /* 228 */ - {0, 12, {0, 12, 30, 12, 0, 30, 51, 15, 27, 51, 51, 31, 0, 0}}, /* 229 */ - {0, 12, {0, 0, 0, 0, 0, 62, 109, 29, 47, 108, 111, 62, 0, 0}}, /* 230 */ - {0, 12, {0, 0, 0, 0, 0, 30, 51, 48, 48, 48, 51, 30, 12, 24}}, /* 231 */ - {0, 12, {0, 24, 12, 6, 0, 30, 51, 51, 63, 48, 51, 30, 0, 0}}, /* 232 */ - {0, 12, {0, 6, 12, 24, 0, 30, 51, 51, 63, 48, 51, 30, 0, 0}}, /* 233 */ - {0, 12, {0, 0, 12, 30, 0, 30, 51, 51, 63, 48, 51, 30, 0, 0}}, /* 234 */ - {0, 12, {0, 0, 18, 18, 0, 30, 51, 51, 63, 48, 51, 30, 0, 0}}, /* 235 */ - {0, 12, {0, 24, 12, 6, 0, 12, 12, 12, 12, 12, 12, 12, 0, 0}}, /* 236 */ - {0, 12, {0, 6, 12, 24, 0, 12, 12, 12, 12, 12, 12, 12, 0, 0}}, /* 237 */ - {0, 12, {0, 0, 12, 30, 0, 12, 12, 12, 12, 12, 12, 12, 0, 0}}, /* 238 */ - {0, 12, {0, 0, 18, 18, 0, 12, 12, 12, 12, 12, 12, 12, 0, 0}}, /* 239 */ - {0, 12, {0, 20, 8, 22, 6, 30, 54, 54, 54, 54, 54, 28, 0, 0}}, /* 240 */ - {0, 12, {0, 0, 10, 20, 0, 62, 51, 51, 51, 51, 51, 51, 0, 0}}, /* 241 */ - {0, 12, {0, 24, 12, 6, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 242 */ - {0, 12, {0, 6, 12, 24, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 243 */ - {0, 12, {0, 0, 12, 30, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 244 */ - {0, 12, {0, 0, 10, 20, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 245 */ - {0, 12, {0, 0, 18, 18, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0}}, /* 246 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 24, 0, 126, 0, 24, 0, 0}}, /* 247 */ - {0, 12, {0, 0, 0, 1, 2, 30, 55, 55, 59, 59, 51, 30, 32, 32}}, /* 248 */ - {0, 12, {0, 16, 24, 12, 4, 51, 51, 51, 51, 51, 51, 31, 0, 0}}, /* 249 */ - {0, 12, {0, 2, 6, 12, 8, 51, 51, 51, 51, 51, 51, 31, 0, 0}}, /* 250 */ - {0, 12, {0, 0, 12, 30, 0, 51, 51, 51, 51, 51, 51, 31, 0, 0}}, /* 251 */ - {0, 12, {0, 0, 18, 18, 0, 51, 51, 51, 51, 51, 51, 31, 0, 0}}, /* 252 */ - {0, 12, {0, 2, 6, 12, 8, 51, 51, 51, 30, 14, 14, 12, 60, 24}}, /* 253 */ - {0, 12, {0, 0, 48, 48, 48, 62, 51, 51, 51, 51, 51, 62, 48, 48}}, /* 254 */ - {0, 12, {0, 0, 18, 18, 0, 51, 51, 51, 30, 14, 14, 12, 60, 24}} /* 255 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 0 */ + {0, 11, {0, 0, 0, 0, 0, 24, 60, 126, 60, 24, 0, 0, 0}}, /* 1 */ + {0, 11, {0, 102, 24, 102, 24, 102, 24, 102, 24, 102, 24, 102, 0}}, /* 2 */ + {0, 11, {0, 108, 108, 124, 108, 108, 0, 30, 12, 12, 12, 12, 0}}, /* 3 */ + {0, 11, {0, 120, 96, 112, 96, 96, 0, 30, 24, 28, 24, 24, 0}}, /* 4 */ + {0, 11, {0, 56, 96, 96, 96, 56, 0, 28, 26, 28, 26, 26, 0}}, /* 5 */ + {0, 11, {0, 96, 96, 96, 96, 120, 0, 30, 24, 28, 24, 24, 0}}, /* 6 */ + {0, 11, {0, 0, 60, 102, 102, 60, 0, 0, 0, 0, 0, 0, 0}}, /* 7 */ + {0, 11, {0, 0, 24, 24, 126, 126, 24, 24, 0, 126, 126, 0, 0}}, /* 8 */ + {0, 11, {0, 102, 118, 126, 110, 102, 0, 24, 24, 24, 24, 30, 0}}, /* 9 */ + {0, 11, {0, 102, 102, 36, 60, 24, 0, 30, 12, 12, 12, 12, 0}}, /* 10 */ + {0, 11, {24, 24, 24, 24, 24, 24, 120, 120, 0, 0, 0, 0, 0}}, /* 11 */ + {0, 11, {0, 0, 0, 0, 0, 0, 120, 120, 24, 24, 24, 24, 24}}, /* 12 */ + {0, 11, {0, 0, 0, 0, 0, 0, 31, 31, 24, 24, 24, 24, 24}}, /* 13 */ + {0, 11, {24, 24, 24, 24, 24, 24, 31, 31, 0, 0, 0, 0, 0}}, /* 14 */ + {0, 11, {24, 24, 24, 24, 24, 24, 127, 127, 24, 24, 24, 24, 24}}, /* 15 */ + {0, 11, {0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 16 */ + {0, 11, {0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 0}}, /* 17 */ + {0, 11, {0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0}}, /* 18 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0}}, /* 19 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 0}}, /* 20 */ + {0, 11, {24, 24, 24, 24, 24, 24, 31, 31, 24, 24, 24, 24, 24}}, /* 21 */ + {0, 11, {24, 24, 24, 24, 24, 24, 120, 120, 24, 24, 24, 24, 24}}, /* 22 */ + {0, 11, {24, 24, 24, 24, 24, 24, 127, 127, 0, 0, 0, 0, 0}}, /* 23 */ + {0, 11, {0, 0, 0, 0, 0, 0, 127, 127, 24, 24, 24, 24, 24}}, /* 24 */ + {0, 11, {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24}}, /* 25 */ + {0, 11, {0, 0, 6, 12, 48, 96, 48, 12, 6, 126, 126, 0, 0}}, /* 26 */ + {0, 11, {0, 0, 96, 48, 12, 6, 12, 48, 96, 126, 126, 0, 0}}, /* 27 */ + {0, 11, {0, 0, 0, 0, 0, 126, 54, 54, 54, 118, 102, 0, 0}}, /* 28 */ + {0, 11, {0, 0, 2, 6, 126, 126, 24, 126, 126, 96, 64, 0, 0}}, /* 29 */ + {0, 11, {0, 0, 28, 54, 48, 48, 124, 48, 48, 54, 92, 0, 0}}, /* 30 */ + {0, 11, {0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 0}}, /* 31 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 32 */ + {0, 11, {0, 0, 24, 24, 24, 24, 24, 24, 0, 24, 24, 0, 0}}, /* 33 */ + {0, 11, {0, 0, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 34 */ + {0, 11, {0, 0, 20, 20, 62, 62, 20, 62, 62, 20, 20, 0, 0}}, /* 35 */ + {0, 11, {0, 0, 24, 60, 90, 88, 60, 26, 90, 60, 24, 0, 0}}, /* 36 */ + {0, 11, {0, 0, 114, 86, 116, 12, 24, 48, 46, 106, 78, 0, 0}}, /* 37 */ + {0, 11, {0, 0, 56, 108, 108, 108, 56, 106, 110, 108, 58, 0, 0}}, /* 38 */ + {0, 11, {0, 0, 28, 28, 24, 48, 0, 0, 0, 0, 0, 0, 0}}, /* 39 */ + {0, 11, {0, 0, 12, 24, 24, 48, 48, 48, 24, 24, 12, 0, 0}}, /* 40 */ + {0, 11, {0, 0, 48, 24, 24, 12, 12, 12, 24, 24, 48, 0, 0}}, /* 41 */ + {0, 11, {0, 0, 0, 0, 36, 24, 126, 126, 24, 36, 0, 0, 0}}, /* 42 */ + {0, 11, {0, 0, 0, 0, 24, 24, 126, 126, 24, 24, 0, 0, 0}}, /* 43 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 24, 48, 0}}, /* 44 */ + {0, 11, {0, 0, 0, 0, 0, 0, 126, 126, 0, 0, 0, 0, 0}}, /* 45 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 60, 24, 0}}, /* 46 */ + {0, 11, {0, 0, 6, 6, 12, 12, 24, 48, 48, 96, 96, 0, 0}}, /* 47 */ + {0, 11, {0, 0, 24, 36, 102, 102, 102, 102, 102, 36, 24, 0, 0}}, /* 48 */ + {0, 11, {0, 0, 24, 56, 88, 24, 24, 24, 24, 24, 126, 0, 0}}, /* 49 */ + {0, 11, {0, 0, 60, 102, 102, 6, 28, 48, 96, 96, 126, 0, 0}}, /* 50 */ + {0, 11, {0, 0, 126, 6, 12, 24, 60, 6, 6, 102, 60, 0, 0}}, /* 51 */ + {0, 11, {0, 0, 6, 14, 30, 54, 102, 102, 126, 6, 6, 0, 0}}, /* 52 */ + {0, 11, {0, 0, 126, 96, 96, 124, 102, 6, 6, 102, 60, 0, 0}}, /* 53 */ + {0, 11, {0, 0, 60, 102, 96, 96, 124, 102, 102, 102, 60, 0, 0}}, /* 54 */ + {0, 11, {0, 0, 126, 6, 6, 12, 12, 24, 24, 48, 48, 0, 0}}, /* 55 */ + {0, 11, {0, 0, 60, 102, 102, 102, 60, 102, 102, 102, 60, 0, 0}}, /* 56 */ + {0, 11, {0, 0, 60, 102, 102, 102, 62, 6, 6, 102, 60, 0, 0}}, /* 57 */ + {0, 11, {0, 0, 0, 0, 24, 60, 24, 0, 0, 24, 60, 24, 0}}, /* 58 */ + {0, 11, {0, 0, 0, 0, 24, 60, 24, 0, 28, 28, 24, 48, 0}}, /* 59 */ + {0, 11, {0, 0, 6, 12, 24, 48, 96, 48, 24, 12, 6, 0, 0}}, /* 60 */ + {0, 11, {0, 0, 0, 0, 126, 126, 0, 126, 126, 0, 0, 0, 0}}, /* 61 */ + {0, 11, {0, 0, 96, 48, 24, 12, 6, 12, 24, 48, 96, 0, 0}}, /* 62 */ + {0, 11, {0, 0, 60, 102, 102, 6, 28, 24, 0, 24, 24, 0, 0}}, /* 63 */ + {0, 11, {0, 0, 60, 70, 70, 94, 86, 94, 64, 70, 60, 0, 0}}, /* 64 */ + {0, 11, {0, 0, 60, 102, 102, 102, 126, 102, 102, 102, 102, 0, 0}}, /* 65 */ + {0, 11, {0, 0, 124, 102, 102, 102, 124, 102, 102, 102, 124, 0, 0}}, /* 66 */ + {0, 11, {0, 0, 60, 102, 96, 96, 96, 96, 96, 102, 60, 0, 0}}, /* 67 */ + {0, 11, {0, 0, 124, 102, 102, 102, 102, 102, 102, 102, 124, 0, 0}}, /* 68 */ + {0, 11, {0, 0, 126, 96, 96, 96, 124, 96, 96, 96, 126, 0, 0}}, /* 69 */ + {0, 11, {0, 0, 126, 96, 96, 96, 124, 96, 96, 96, 96, 0, 0}}, /* 70 */ + {0, 11, {0, 0, 60, 102, 96, 96, 110, 102, 102, 102, 62, 0, 0}}, /* 71 */ + {0, 11, {0, 0, 102, 102, 102, 102, 126, 102, 102, 102, 102, 0, 0}}, /* 72 */ + {0, 11, {0, 0, 126, 24, 24, 24, 24, 24, 24, 24, 126, 0, 0}}, /* 73 */ + {0, 11, {0, 0, 6, 6, 6, 6, 6, 6, 6, 102, 60, 0, 0}}, /* 74 */ + {0, 11, {0, 0, 98, 102, 108, 120, 112, 120, 108, 102, 98, 0, 0}}, /* 75 */ + {0, 11, {0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 126, 0, 0}}, /* 76 */ + {0, 11, {0, 0, 66, 102, 126, 126, 102, 102, 102, 102, 102, 0, 0}}, /* 77 */ + {0, 11, {0, 0, 102, 102, 118, 118, 126, 110, 110, 102, 102, 0, 0}}, /* 78 */ + {0, 11, {0, 0, 60, 102, 102, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 79 */ + {0, 11, {0, 0, 124, 102, 102, 102, 124, 96, 96, 96, 96, 0, 0}}, /* 80 */ + {0, 11, {0, 0, 60, 102, 102, 102, 102, 102, 118, 110, 60, 6, 0}}, /* 81 */ + {0, 11, {0, 0, 124, 102, 102, 102, 124, 120, 108, 102, 98, 0, 0}}, /* 82 */ + {0, 11, {0, 0, 60, 102, 96, 96, 60, 6, 6, 102, 60, 0, 0}}, /* 83 */ + {0, 11, {0, 0, 126, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0}}, /* 84 */ + {0, 11, {0, 0, 102, 102, 102, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 85 */ + {0, 11, {0, 0, 102, 102, 102, 36, 36, 60, 24, 24, 24, 0, 0}}, /* 86 */ + {0, 11, {0, 0, 102, 102, 102, 102, 102, 126, 126, 102, 66, 0, 0}}, /* 87 */ + {0, 11, {0, 0, 66, 102, 36, 60, 24, 60, 36, 102, 66, 0, 0}}, /* 88 */ + {0, 11, {0, 0, 102, 102, 60, 60, 24, 24, 24, 24, 24, 0, 0}}, /* 89 */ + {0, 11, {0, 0, 126, 6, 6, 12, 24, 48, 96, 96, 126, 0, 0}}, /* 90 */ + {0, 11, {0, 0, 60, 48, 48, 48, 48, 48, 48, 48, 60, 0, 0}}, /* 91 */ + {0, 11, {0, 0, 96, 96, 48, 48, 24, 12, 12, 6, 6, 0, 0}}, /* 92 */ + {0, 11, {0, 0, 60, 12, 12, 12, 12, 12, 12, 12, 60, 0, 0}}, /* 93 */ + {0, 11, {0, 0, 24, 60, 102, 66, 0, 0, 0, 0, 0, 0, 0}}, /* 94 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 126, 0}}, /* 95 */ + {0, 11, {0, 0, 56, 56, 24, 12, 0, 0, 0, 0, 0, 0, 0}}, /* 96 */ + {0, 11, {0, 0, 0, 0, 0, 60, 6, 62, 102, 102, 62, 0, 0}}, /* 97 */ + {0, 11, {0, 0, 96, 96, 96, 124, 102, 102, 102, 102, 124, 0, 0}}, /* 98 */ + {0, 11, {0, 0, 0, 0, 0, 60, 102, 96, 96, 102, 60, 0, 0}}, /* 99 */ + {0, 11, {0, 0, 6, 6, 6, 62, 102, 102, 102, 102, 62, 0, 0}}, /* 100 */ + {0, 11, {0, 0, 0, 0, 0, 60, 102, 126, 96, 102, 60, 0, 0}}, /* 101 */ + {0, 11, {0, 0, 28, 54, 48, 48, 120, 48, 48, 48, 48, 0, 0}}, /* 102 */ + {0, 11, {0, 0, 0, 0, 0, 58, 102, 102, 60, 96, 60, 102, 60}}, /* 103 */ + {0, 11, {0, 0, 96, 96, 96, 124, 102, 102, 102, 102, 102, 0, 0}}, /* 104 */ + {0, 11, {0, 0, 24, 24, 0, 56, 24, 24, 24, 24, 126, 0, 0}}, /* 105 */ + {0, 11, {0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 6, 102, 60}}, /* 106 */ + {0, 11, {0, 0, 96, 96, 96, 102, 108, 120, 120, 108, 102, 0, 0}}, /* 107 */ + {0, 11, {0, 0, 56, 24, 24, 24, 24, 24, 24, 24, 126, 0, 0}}, /* 108 */ + {0, 11, {0, 0, 0, 0, 0, 108, 126, 126, 102, 102, 102, 0, 0}}, /* 109 */ + {0, 11, {0, 0, 0, 0, 0, 124, 102, 102, 102, 102, 102, 0, 0}}, /* 110 */ + {0, 11, {0, 0, 0, 0, 0, 60, 102, 102, 102, 102, 60, 0, 0}}, /* 111 */ + {0, 11, {0, 0, 0, 0, 0, 124, 102, 102, 102, 124, 96, 96, 96}}, /* 112 */ + {0, 11, {0, 0, 0, 0, 0, 62, 102, 102, 102, 62, 6, 6, 6}}, /* 113 */ + {0, 11, {0, 0, 0, 0, 0, 124, 102, 96, 96, 96, 96, 0, 0}}, /* 114 */ + {0, 11, {0, 0, 0, 0, 0, 60, 102, 48, 12, 102, 60, 0, 0}}, /* 115 */ + {0, 11, {0, 0, 0, 48, 48, 124, 48, 48, 48, 54, 28, 0, 0}}, /* 116 */ + {0, 11, {0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 62, 0, 0}}, /* 117 */ + {0, 11, {0, 0, 0, 0, 0, 102, 102, 102, 60, 60, 24, 0, 0}}, /* 118 */ + {0, 11, {0, 0, 0, 0, 0, 102, 102, 102, 126, 126, 36, 0, 0}}, /* 119 */ + {0, 11, {0, 0, 0, 0, 0, 102, 102, 60, 60, 102, 102, 0, 0}}, /* 120 */ + {0, 11, {0, 0, 0, 0, 0, 102, 102, 102, 102, 62, 6, 102, 60}}, /* 121 */ + {0, 11, {0, 0, 0, 0, 0, 126, 6, 12, 48, 96, 126, 0, 0}}, /* 122 */ + {0, 11, {0, 0, 28, 48, 48, 24, 48, 24, 48, 48, 28, 0, 0}}, /* 123 */ + {0, 11, {0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0}}, /* 124 */ + {0, 11, {0, 0, 56, 12, 12, 24, 12, 24, 12, 12, 56, 0, 0}}, /* 125 */ + {0, 11, {0, 0, 50, 126, 76, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 126 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 127 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 128 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 129 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 130 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 131 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 132 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 133 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 134 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 135 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 136 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 137 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 138 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 139 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 140 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 141 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 142 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 143 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 144 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 145 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 146 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 147 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 148 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 149 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 150 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 151 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 152 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 153 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 154 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 155 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 156 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 157 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 158 */ + {0, 11, {0, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0}}, /* 159 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 160 */ + {0, 11, {0, 24, 24, 0, 24, 24, 24, 24, 24, 24, 24, 0, 0}}, /* 161 */ + {0, 11, {0, 0, 8, 62, 106, 104, 104, 106, 62, 8, 0, 0, 0}}, /* 162 */ + {0, 11, {0, 0, 28, 54, 48, 48, 124, 48, 48, 54, 92, 0, 0}}, /* 163 */ + {0, 11, {0, 0, 0, 0, 102, 126, 36, 36, 126, 102, 0, 0, 0}}, /* 164 */ + {0, 11, {0, 0, 102, 102, 60, 60, 126, 24, 126, 24, 24, 0, 0}}, /* 165 */ + {0, 11, {0, 24, 24, 24, 24, 0, 0, 24, 24, 24, 24, 0, 0}}, /* 166 */ + {0, 11, {0, 60, 102, 96, 60, 102, 102, 60, 6, 102, 60, 0, 0}}, /* 167 */ + {0, 11, {0, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 168 */ + {0, 11, {0, 60, 102, 66, 90, 114, 114, 90, 66, 102, 60, 0, 0}}, /* 169 */ + {0, 11, {0, 0, 60, 6, 62, 38, 62, 0, 62, 0, 0, 0, 0}}, /* 170 */ + {0, 11, {0, 0, 0, 26, 52, 104, 80, 104, 52, 26, 0, 0, 0}}, /* 171 */ + {0, 11, {0, 0, 0, 0, 0, 126, 126, 2, 2, 0, 0, 0, 0}}, /* 172 */ + {0, 11, {0, 0, 0, 0, 0, 62, 62, 0, 0, 0, 0, 0, 0}}, /* 173 */ + {0, 11, {0, 60, 102, 66, 94, 86, 94, 90, 86, 102, 60, 0, 0}}, /* 174 */ + {0, 11, {0, 62, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 175 */ + {0, 11, {0, 0, 60, 102, 102, 60, 0, 0, 0, 0, 0, 0, 0}}, /* 176 */ + {0, 11, {0, 0, 24, 24, 126, 126, 24, 24, 0, 126, 126, 0, 0}}, /* 177 */ + {0, 11, {0, 112, 88, 24, 48, 96, 120, 0, 0, 0, 0, 0, 0}}, /* 178 */ + {0, 11, {0, 112, 88, 48, 24, 88, 112, 0, 0, 0, 0, 0, 0}}, /* 179 */ + {0, 11, {0, 12, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 180 */ + {0, 11, {0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 126, 64, 0}}, /* 181 */ + {0, 11, {0, 0, 62, 126, 122, 122, 122, 58, 26, 26, 26, 0, 0}}, /* 182 */ + {0, 11, {0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 0, 0}}, /* 183 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 48}}, /* 184 */ + {0, 11, {0, 48, 112, 48, 48, 48, 120, 0, 0, 0, 0, 0, 0}}, /* 185 */ + {0, 11, {0, 28, 62, 34, 62, 28, 0, 62, 0, 0, 0, 0, 0}}, /* 186 */ + {0, 11, {0, 0, 0, 88, 44, 22, 10, 22, 44, 88, 0, 0, 0}}, /* 187 */ + {0, 11, {0, 48, 112, 48, 48, 50, 126, 14, 26, 30, 6, 0, 0}}, /* 188 */ + {0, 11, {0, 48, 112, 48, 48, 60, 118, 6, 12, 24, 30, 0, 0}}, /* 189 */ + {0, 11, {0, 112, 88, 48, 24, 90, 118, 14, 26, 30, 6, 0, 0}}, /* 190 */ + {0, 11, {0, 24, 24, 0, 24, 24, 48, 96, 102, 102, 60, 0, 0}}, /* 191 */ + {0, 11, {0, 24, 12, 0, 24, 60, 102, 102, 126, 102, 102, 0, 0}}, /* 192 */ + {0, 11, {0, 12, 24, 0, 24, 60, 102, 102, 126, 102, 102, 0, 0}}, /* 193 */ + {0, 11, {0, 56, 108, 0, 24, 60, 102, 102, 126, 102, 102, 0, 0}}, /* 194 */ + {0, 11, {0, 52, 88, 0, 24, 60, 102, 102, 126, 102, 102, 0, 0}}, /* 195 */ + {0, 11, {0, 102, 102, 0, 24, 60, 102, 102, 126, 102, 102, 0, 0}}, /* 196 */ + {0, 11, {0, 60, 36, 60, 24, 60, 102, 102, 126, 102, 102, 0, 0}}, /* 197 */ + {0, 11, {0, 0, 62, 124, 108, 108, 110, 124, 108, 108, 110, 0, 0}}, /* 198 */ + {0, 11, {0, 0, 60, 102, 96, 96, 96, 96, 96, 102, 60, 24, 48}}, /* 199 */ + {0, 11, {0, 24, 12, 0, 126, 96, 96, 120, 96, 96, 126, 0, 0}}, /* 200 */ + {0, 11, {0, 12, 24, 0, 126, 96, 96, 120, 96, 96, 126, 0, 0}}, /* 201 */ + {0, 11, {0, 56, 108, 0, 126, 96, 96, 120, 96, 96, 126, 0, 0}}, /* 202 */ + {0, 11, {0, 102, 102, 0, 126, 96, 96, 120, 96, 96, 126, 0, 0}}, /* 203 */ + {0, 11, {0, 24, 12, 0, 126, 24, 24, 24, 24, 24, 126, 0, 0}}, /* 204 */ + {0, 11, {0, 12, 24, 0, 126, 24, 24, 24, 24, 24, 126, 0, 0}}, /* 205 */ + {0, 11, {0, 56, 108, 0, 126, 24, 24, 24, 24, 24, 126, 0, 0}}, /* 206 */ + {0, 11, {0, 102, 102, 0, 126, 24, 24, 24, 24, 24, 126, 0, 0}}, /* 207 */ + {0, 11, {0, 0, 124, 54, 54, 54, 118, 54, 54, 54, 124, 0, 0}}, /* 208 */ + {0, 11, {0, 52, 88, 0, 102, 102, 118, 126, 110, 102, 102, 0, 0}}, /* 209 */ + {0, 11, {0, 24, 12, 0, 60, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 210 */ + {0, 11, {0, 12, 24, 0, 60, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 211 */ + {0, 11, {0, 56, 108, 0, 60, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 212 */ + {0, 11, {0, 52, 88, 0, 60, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 213 */ + {0, 11, {0, 102, 102, 0, 60, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 214 */ + {0, 11, {0, 0, 0, 0, 0, 102, 60, 24, 60, 102, 0, 0, 0}}, /* 215 */ + {0, 11, {0, 0, 2, 60, 110, 110, 110, 118, 118, 118, 60, 64, 0}}, /* 216 */ + {0, 11, {0, 24, 12, 0, 102, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 217 */ + {0, 11, {0, 12, 24, 0, 102, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 218 */ + {0, 11, {0, 56, 108, 0, 102, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 219 */ + {0, 11, {0, 102, 102, 0, 102, 102, 102, 102, 102, 102, 60, 0, 0}}, /* 220 */ + {0, 11, {0, 12, 24, 0, 102, 36, 60, 24, 24, 24, 24, 0, 0}}, /* 221 */ + {0, 11, {0, 0, 96, 124, 102, 102, 102, 124, 96, 96, 96, 0, 0}}, /* 222 */ + {0, 11, {0, 0, 0, 60, 102, 102, 124, 102, 102, 102, 124, 64, 0}}, /* 223 */ + {0, 11, {0, 24, 12, 0, 0, 60, 6, 62, 102, 110, 62, 0, 0}}, /* 224 */ + {0, 11, {0, 12, 24, 0, 0, 60, 6, 62, 102, 110, 62, 0, 0}}, /* 225 */ + {0, 11, {0, 56, 108, 0, 0, 60, 6, 62, 102, 110, 62, 0, 0}}, /* 226 */ + {0, 11, {0, 52, 88, 0, 0, 60, 6, 62, 102, 110, 62, 0, 0}}, /* 227 */ + {0, 11, {0, 54, 54, 0, 0, 60, 6, 62, 102, 110, 62, 0, 0}}, /* 228 */ + {0, 11, {0, 28, 20, 28, 0, 60, 6, 62, 102, 110, 62, 0, 0}}, /* 229 */ + {0, 11, {0, 0, 0, 0, 0, 60, 26, 62, 88, 90, 52, 0, 0}}, /* 230 */ + {0, 11, {0, 0, 0, 0, 0, 60, 102, 96, 96, 102, 60, 24, 48}}, /* 231 */ + {0, 11, {0, 24, 12, 0, 0, 60, 102, 126, 96, 102, 60, 0, 0}}, /* 232 */ + {0, 11, {0, 12, 24, 0, 0, 60, 102, 126, 96, 102, 60, 0, 0}}, /* 233 */ + {0, 11, {0, 56, 108, 0, 0, 60, 102, 126, 96, 102, 60, 0, 0}}, /* 234 */ + {0, 11, {0, 54, 54, 0, 0, 60, 102, 126, 96, 102, 60, 0, 0}}, /* 235 */ + {0, 11, {0, 24, 12, 0, 0, 56, 24, 24, 24, 24, 60, 0, 0}}, /* 236 */ + {0, 11, {0, 12, 24, 0, 0, 56, 24, 24, 24, 24, 60, 0, 0}}, /* 237 */ + {0, 11, {0, 56, 108, 0, 0, 56, 24, 24, 24, 24, 60, 0, 0}}, /* 238 */ + {0, 11, {0, 54, 54, 0, 0, 56, 24, 24, 24, 24, 60, 0, 0}}, /* 239 */ + {0, 11, {0, 36, 24, 24, 40, 60, 102, 102, 102, 102, 60, 0, 0}}, /* 240 */ + {0, 11, {0, 52, 88, 0, 0, 124, 118, 102, 102, 102, 102, 0, 0}}, /* 241 */ + {0, 11, {0, 24, 12, 0, 0, 60, 102, 102, 102, 102, 60, 0, 0}}, /* 242 */ + {0, 11, {0, 12, 24, 0, 0, 60, 102, 102, 102, 102, 60, 0, 0}}, /* 243 */ + {0, 11, {0, 56, 108, 0, 0, 60, 102, 102, 102, 102, 60, 0, 0}}, /* 244 */ + {0, 11, {0, 52, 88, 0, 0, 60, 102, 102, 102, 102, 60, 0, 0}}, /* 245 */ + {0, 11, {0, 54, 54, 0, 0, 60, 102, 102, 102, 102, 60, 0, 0}}, /* 246 */ + {0, 11, {0, 0, 0, 24, 24, 0, 126, 0, 24, 24, 0, 0, 0}}, /* 247 */ + {0, 11, {0, 0, 0, 2, 60, 102, 110, 102, 118, 102, 60, 64, 0}}, /* 248 */ + {0, 11, {0, 24, 12, 0, 0, 102, 102, 102, 102, 110, 62, 0, 0}}, /* 249 */ + {0, 11, {0, 12, 24, 0, 0, 102, 102, 102, 102, 110, 62, 0, 0}}, /* 250 */ + {0, 11, {0, 56, 108, 0, 0, 102, 102, 102, 102, 110, 62, 0, 0}}, /* 251 */ + {0, 11, {0, 54, 54, 0, 0, 102, 102, 102, 102, 110, 62, 0, 0}}, /* 252 */ + {0, 11, {0, 12, 24, 0, 0, 102, 102, 102, 110, 62, 6, 102, 60}}, /* 253 */ + {0, 11, {0, 0, 0, 96, 96, 124, 118, 102, 102, 118, 124, 96, 96}}, /* 254 */ + {0, 11, {0, 54, 54, 0, 0, 102, 102, 102, 110, 62, 6, 102, 60}} /* 255 */ }; diff --git a/src/text/font/font.c b/src/text/font/font.c index e1c5d89..039db26 100644 --- a/src/text/font/font.c +++ b/src/text/font/font.c @@ -2,263 +2,263 @@ /** * Copyright notice: - * "Public domain font. Share and enjoy." + * "(null)" */ MwFont MwFontData[] = { - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0 */ - {0, 12, {0, 0, 12, 12, 30, 30, 63, 63, 30, 30, 12, 12, 0, 0}}, /* 1 */ - {0, 12, {42, 85, 42, 85, 42, 85, 42, 85, 42, 85, 42, 85, 42, 85}}, /* 2 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 3 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 4 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 5 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 6 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 7 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 8 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 9 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 10 */ - {0, 12, {8, 8, 8, 8, 8, 8, 8, 120, 0, 0, 0, 0, 0, 0}}, /* 11 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 120, 8, 8, 8, 8, 8, 8}}, /* 12 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 15, 8, 8, 8, 8, 8, 8}}, /* 13 */ - {0, 12, {8, 8, 8, 8, 8, 8, 8, 15, 0, 0, 0, 0, 0, 0}}, /* 14 */ - {0, 12, {8, 8, 8, 8, 8, 8, 8, 127, 8, 8, 8, 8, 8, 8}}, /* 15 */ - {0, 12, {127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 16 */ - {0, 12, {0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 17 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0}}, /* 18 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0}}, /* 19 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127}}, /* 20 */ - {0, 12, {8, 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8}}, /* 21 */ - {0, 12, {8, 8, 8, 8, 8, 8, 8, 120, 8, 8, 8, 8, 8, 8}}, /* 22 */ - {0, 12, {8, 8, 8, 8, 8, 8, 8, 127, 0, 0, 0, 0, 0, 0}}, /* 23 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 127, 8, 8, 8, 8, 8, 8}}, /* 24 */ - {0, 12, {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}}, /* 25 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 26 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 27 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 28 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 29 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 30 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 31 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 32 */ - {0, 12, {0, 0, 8, 8, 8, 8, 8, 8, 8, 0, 8, 8, 0, 0}}, /* 33 */ - {0, 12, {54, 18, 18, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 34 */ - {0, 12, {0, 0, 5, 5, 5, 63, 10, 10, 63, 20, 20, 20, 0, 0}}, /* 35 */ - {0, 12, {0, 0, 4, 30, 37, 37, 20, 14, 5, 37, 37, 30, 4, 0}}, /* 36 */ - {0, 12, {0, 0, 25, 37, 38, 28, 4, 8, 14, 25, 41, 38, 0, 0}}, /* 37 */ - {0, 12, {0, 0, 12, 18, 18, 18, 12, 25, 37, 34, 38, 25, 0, 0}}, /* 38 */ - {0, 12, {24, 8, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 39 */ - {0, 12, {0, 1, 2, 4, 4, 8, 8, 8, 8, 8, 4, 4, 2, 1}}, /* 40 */ - {0, 12, {0, 32, 16, 8, 8, 4, 4, 4, 4, 4, 8, 8, 16, 32}}, /* 41 */ - {0, 12, {0, 0, 0, 4, 21, 14, 4, 4, 14, 21, 4, 0, 0, 0}}, /* 42 */ - {0, 12, {0, 0, 0, 0, 8, 8, 8, 62, 8, 8, 8, 0, 0, 0}}, /* 43 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 8, 8, 16}}, /* 44 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0}}, /* 45 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0}}, /* 46 */ - {0, 12, {0, 1, 1, 2, 2, 4, 4, 4, 8, 8, 16, 16, 32, 32}}, /* 47 */ - {0, 12, {0, 0, 12, 18, 33, 33, 33, 33, 33, 33, 18, 12, 0, 0}}, /* 48 */ - {0, 12, {0, 0, 4, 12, 20, 4, 4, 4, 4, 4, 4, 31, 0, 0}}, /* 49 */ - {0, 12, {0, 0, 30, 33, 33, 1, 2, 2, 4, 8, 16, 63, 0, 0}}, /* 50 */ - {0, 12, {0, 0, 30, 33, 33, 1, 14, 1, 1, 33, 33, 30, 0, 0}}, /* 51 */ - {0, 12, {0, 0, 2, 6, 10, 10, 18, 18, 34, 63, 2, 2, 0, 0}}, /* 52 */ - {0, 12, {0, 0, 63, 32, 32, 62, 33, 1, 1, 33, 33, 30, 0, 0}}, /* 53 */ - {0, 12, {0, 0, 14, 17, 33, 32, 46, 49, 33, 33, 33, 30, 0, 0}}, /* 54 */ - {0, 12, {0, 0, 63, 33, 34, 2, 4, 4, 4, 4, 4, 4, 0, 0}}, /* 55 */ - {0, 12, {0, 0, 30, 33, 33, 18, 12, 18, 33, 33, 33, 30, 0, 0}}, /* 56 */ - {0, 12, {0, 0, 30, 33, 33, 33, 35, 29, 1, 33, 34, 28, 0, 0}}, /* 57 */ - {0, 12, {0, 0, 0, 0, 8, 8, 0, 0, 0, 8, 8, 0, 0, 0}}, /* 58 */ - {0, 12, {0, 0, 0, 0, 8, 8, 0, 0, 0, 24, 8, 8, 16, 0}}, /* 59 */ - {0, 12, {0, 0, 0, 2, 4, 8, 16, 32, 16, 8, 4, 2, 0, 0}}, /* 60 */ - {0, 12, {0, 0, 0, 0, 0, 63, 0, 0, 63, 0, 0, 0, 0, 0}}, /* 61 */ - {0, 12, {0, 0, 0, 32, 16, 8, 4, 2, 4, 8, 16, 32, 0, 0}}, /* 62 */ - {0, 12, {0, 0, 30, 33, 33, 2, 4, 4, 4, 0, 4, 4, 0, 0}}, /* 63 */ - {0, 12, {0, 0, 14, 17, 39, 41, 41, 41, 41, 39, 16, 15, 0, 0}}, /* 64 */ - {0, 12, {0, 0, 8, 12, 20, 18, 34, 33, 63, 33, 33, 33, 0, 0}}, /* 65 */ - {0, 12, {0, 0, 62, 33, 33, 34, 62, 33, 33, 33, 33, 62, 0, 0}}, /* 66 */ - {0, 12, {0, 0, 30, 33, 33, 32, 32, 32, 32, 33, 33, 30, 0, 0}}, /* 67 */ - {0, 12, {0, 0, 60, 34, 33, 33, 33, 33, 33, 33, 34, 60, 0, 0}}, /* 68 */ - {0, 12, {0, 0, 63, 32, 32, 32, 62, 32, 32, 32, 32, 63, 0, 0}}, /* 69 */ - {0, 12, {0, 0, 63, 32, 32, 32, 62, 32, 32, 32, 32, 32, 0, 0}}, /* 70 */ - {0, 12, {0, 0, 30, 33, 33, 32, 32, 39, 33, 33, 33, 30, 0, 0}}, /* 71 */ - {0, 12, {0, 0, 33, 33, 33, 33, 63, 33, 33, 33, 33, 33, 0, 0}}, /* 72 */ - {0, 12, {0, 0, 31, 4, 4, 4, 4, 4, 4, 4, 4, 31, 0, 0}}, /* 73 */ - {0, 12, {0, 0, 1, 1, 1, 1, 1, 1, 1, 33, 34, 28, 0, 0}}, /* 74 */ - {0, 12, {0, 0, 33, 34, 36, 40, 56, 36, 36, 34, 33, 33, 0, 0}}, /* 75 */ - {0, 12, {0, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 63, 0, 0}}, /* 76 */ - {0, 12, {0, 0, 33, 35, 51, 53, 45, 41, 41, 33, 33, 33, 0, 0}}, /* 77 */ - {0, 12, {0, 0, 49, 49, 41, 41, 41, 37, 37, 37, 35, 35, 0, 0}}, /* 78 */ - {0, 12, {0, 0, 30, 33, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 79 */ - {0, 12, {0, 0, 62, 33, 33, 33, 33, 62, 32, 32, 32, 32, 0, 0}}, /* 80 */ - {0, 12, {0, 0, 30, 33, 33, 33, 33, 33, 57, 37, 35, 30, 2, 1}}, /* 81 */ - {0, 12, {0, 0, 62, 33, 33, 33, 62, 34, 33, 33, 33, 33, 0, 0}}, /* 82 */ - {0, 12, {0, 0, 30, 33, 33, 16, 8, 4, 2, 33, 33, 30, 0, 0}}, /* 83 */ - {0, 12, {0, 0, 63, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 84 */ - {0, 12, {0, 0, 33, 33, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 85 */ - {0, 12, {0, 0, 33, 33, 33, 34, 18, 18, 20, 12, 8, 8, 0, 0}}, /* 86 */ - {0, 12, {0, 0, 37, 37, 37, 37, 37, 63, 18, 18, 18, 18, 0, 0}}, /* 87 */ - {0, 12, {0, 0, 33, 33, 18, 18, 12, 12, 18, 18, 33, 33, 0, 0}}, /* 88 */ - {0, 12, {0, 0, 33, 33, 34, 18, 20, 12, 8, 8, 8, 8, 0, 0}}, /* 89 */ - {0, 12, {0, 0, 63, 1, 2, 4, 4, 8, 16, 16, 32, 63, 0, 0}}, /* 90 */ - {0, 12, {0, 15, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 15}}, /* 91 */ - {0, 12, {0, 32, 32, 16, 16, 8, 8, 8, 4, 4, 2, 2, 1, 1}}, /* 92 */ - {0, 12, {0, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 60}}, /* 93 */ - {0, 12, {12, 18, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 94 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}}, /* 95 */ - {0, 12, {6, 4, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 96 */ - {0, 12, {0, 0, 0, 0, 0, 30, 33, 7, 25, 33, 35, 29, 0, 0}}, /* 97 */ - {0, 12, {0, 0, 32, 32, 32, 46, 49, 33, 33, 33, 49, 46, 0, 0}}, /* 98 */ - {0, 12, {0, 0, 0, 0, 0, 30, 33, 32, 32, 32, 33, 30, 0, 0}}, /* 99 */ - {0, 12, {0, 0, 1, 1, 1, 29, 35, 33, 33, 33, 35, 29, 0, 0}}, /* 100 */ - {0, 12, {0, 0, 0, 0, 0, 30, 33, 33, 63, 32, 33, 30, 0, 0}}, /* 101 */ - {0, 12, {0, 0, 6, 9, 8, 8, 62, 8, 8, 8, 8, 8, 0, 0}}, /* 102 */ - {0, 12, {0, 0, 0, 0, 0, 29, 34, 34, 34, 28, 16, 46, 33, 30}}, /* 103 */ - {0, 12, {0, 0, 32, 32, 32, 46, 49, 33, 33, 33, 33, 33, 0, 0}}, /* 104 */ - {0, 12, {0, 0, 8, 8, 0, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 105 */ - {0, 12, {0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 34, 28}}, /* 106 */ - {0, 12, {0, 0, 32, 32, 32, 34, 36, 40, 56, 36, 34, 33, 0, 0}}, /* 107 */ - {0, 12, {0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 108 */ - {0, 12, {0, 0, 0, 0, 0, 62, 41, 41, 41, 41, 41, 41, 0, 0}}, /* 109 */ - {0, 12, {0, 0, 0, 0, 0, 46, 49, 33, 33, 33, 33, 33, 0, 0}}, /* 110 */ - {0, 12, {0, 0, 0, 0, 0, 30, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 111 */ - {0, 12, {0, 0, 0, 0, 0, 46, 49, 33, 33, 33, 49, 46, 32, 32}}, /* 112 */ - {0, 12, {0, 0, 0, 0, 0, 29, 35, 33, 33, 33, 35, 29, 1, 1}}, /* 113 */ - {0, 12, {0, 0, 0, 0, 0, 46, 49, 33, 32, 32, 32, 32, 0, 0}}, /* 114 */ - {0, 12, {0, 0, 0, 0, 0, 30, 33, 16, 12, 2, 33, 30, 0, 0}}, /* 115 */ - {0, 12, {0, 0, 8, 8, 8, 63, 8, 8, 8, 8, 8, 7, 0, 0}}, /* 116 */ - {0, 12, {0, 0, 0, 0, 0, 33, 33, 33, 33, 33, 35, 29, 0, 0}}, /* 117 */ - {0, 12, {0, 0, 0, 0, 0, 33, 33, 17, 18, 10, 12, 4, 0, 0}}, /* 118 */ - {0, 12, {0, 0, 0, 0, 0, 37, 37, 37, 63, 18, 18, 18, 0, 0}}, /* 119 */ - {0, 12, {0, 0, 0, 0, 0, 33, 33, 18, 12, 18, 33, 33, 0, 0}}, /* 120 */ - {0, 12, {0, 0, 0, 0, 0, 33, 33, 17, 18, 10, 14, 4, 36, 24}}, /* 121 */ - {0, 12, {0, 0, 0, 0, 0, 63, 2, 4, 8, 8, 16, 63, 0, 0}}, /* 122 */ - {0, 12, {0, 3, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 3}}, /* 123 */ - {0, 12, {0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}}, /* 124 */ - {0, 12, {0, 48, 8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 48}}, /* 125 */ - {0, 12, {0, 16, 41, 37, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 126 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 127 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 128 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 129 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 130 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 131 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 132 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 133 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 134 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 135 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 136 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 137 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 138 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 139 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 140 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 141 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 142 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 143 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 144 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 145 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 146 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 147 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 148 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 149 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 150 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 151 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 152 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 153 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 154 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 155 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 156 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 157 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 158 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 159 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 160 */ - {0, 12, {0, 0, 8, 8, 0, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 161 */ - {0, 12, {0, 0, 0, 0, 8, 31, 41, 40, 40, 40, 41, 31, 8, 0}}, /* 162 */ - {0, 12, {0, 0, 0, 12, 18, 16, 16, 60, 16, 16, 60, 18, 0, 0}}, /* 163 */ - {0, 12, {0, 0, 0, 0, 33, 30, 18, 18, 30, 33, 0, 0, 0, 0}}, /* 164 */ - {0, 12, {0, 0, 33, 18, 12, 63, 4, 4, 63, 4, 4, 4, 0, 0}}, /* 165 */ - {0, 12, {0, 0, 8, 8, 8, 8, 0, 0, 8, 8, 8, 8, 0, 0}}, /* 166 */ - {0, 12, {0, 30, 33, 16, 12, 18, 33, 18, 12, 2, 33, 30, 0, 0}}, /* 167 */ - {0, 12, {0, 36, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 168 */ - {0, 12, {0, 30, 33, 45, 51, 49, 49, 49, 51, 45, 33, 30, 0, 0}}, /* 169 */ - {0, 12, {0, 14, 17, 15, 17, 19, 13, 0, 31, 0, 0, 0, 0, 0}}, /* 170 */ - {0, 12, {0, 0, 0, 0, 0, 5, 10, 20, 40, 20, 10, 5, 0, 0}}, /* 171 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 124, 4, 4, 4, 0, 0}}, /* 172 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0}}, /* 173 */ - {0, 12, {0, 30, 33, 61, 51, 51, 61, 51, 51, 51, 33, 30, 0, 0}}, /* 174 */ - {0, 12, {0, 0, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 175 */ - {0, 12, {0, 24, 36, 36, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 176 */ - {0, 12, {0, 0, 0, 0, 0, 0, 8, 8, 62, 8, 8, 62, 0, 0}}, /* 177 */ - {0, 12, {0, 24, 36, 4, 8, 16, 32, 60, 0, 0, 0, 0, 0, 0}}, /* 178 */ - {0, 12, {0, 24, 36, 4, 24, 4, 36, 24, 0, 0, 0, 0, 0, 0}}, /* 179 */ - {0, 12, {0, 4, 8, 16, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 180 */ - {0, 12, {0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 54, 42, 32, 32}}, /* 181 */ - {0, 12, {0, 0, 30, 42, 42, 42, 42, 26, 10, 10, 10, 10, 10, 14}}, /* 182 */ - {0, 12, {0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0}}, /* 183 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 16}}, /* 184 */ - {0, 12, {0, 0, 16, 48, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0}}, /* 185 */ - {0, 12, {0, 0, 12, 18, 18, 12, 0, 30, 0, 0, 0, 0, 0, 0}}, /* 186 */ - {0, 12, {0, 0, 0, 0, 0, 40, 20, 10, 5, 10, 20, 40, 0, 0}}, /* 187 */ - {0, 12, {0, 0, 16, 49, 18, 18, 20, 9, 11, 21, 39, 33, 0, 0}}, /* 188 */ - {0, 12, {0, 0, 16, 49, 18, 18, 20, 10, 13, 17, 34, 39, 0, 0}}, /* 189 */ - {0, 12, {0, 0, 49, 9, 18, 12, 52, 9, 19, 21, 39, 1, 0, 0}}, /* 190 */ - {0, 12, {0, 0, 0, 4, 4, 0, 4, 4, 4, 4, 2, 33, 33, 30}}, /* 191 */ - {0, 12, {16, 12, 0, 12, 20, 18, 34, 33, 63, 33, 33, 33, 0, 0}}, /* 192 */ - {0, 12, {2, 12, 0, 12, 20, 18, 34, 33, 63, 33, 33, 33, 0, 0}}, /* 193 */ - {0, 12, {12, 18, 0, 12, 20, 18, 34, 33, 63, 33, 33, 33, 0, 0}}, /* 194 */ - {0, 12, {10, 20, 0, 12, 20, 18, 34, 33, 63, 33, 33, 33, 0, 0}}, /* 195 */ - {0, 12, {0, 18, 0, 12, 20, 18, 34, 33, 63, 33, 33, 33, 0, 0}}, /* 196 */ - {0, 12, {8, 0, 8, 12, 20, 18, 34, 33, 63, 33, 33, 33, 0, 0}}, /* 197 */ - {0, 12, {0, 0, 31, 40, 40, 40, 78, 120, 72, 72, 72, 79, 0, 0}}, /* 198 */ - {0, 12, {0, 0, 30, 33, 33, 32, 32, 32, 32, 33, 33, 30, 4, 8}}, /* 199 */ - {0, 12, {16, 12, 0, 63, 32, 32, 32, 62, 32, 32, 32, 63, 0, 0}}, /* 200 */ - {0, 12, {2, 12, 0, 63, 32, 32, 32, 62, 32, 32, 32, 63, 0, 0}}, /* 201 */ - {0, 12, {12, 18, 0, 63, 32, 32, 32, 62, 32, 32, 32, 63, 0, 0}}, /* 202 */ - {0, 12, {0, 18, 0, 63, 32, 32, 32, 62, 32, 32, 32, 63, 0, 0}}, /* 203 */ - {0, 12, {8, 6, 0, 31, 4, 4, 4, 4, 4, 4, 4, 31, 0, 0}}, /* 204 */ - {0, 12, {2, 12, 0, 31, 4, 4, 4, 4, 4, 4, 4, 31, 0, 0}}, /* 205 */ - {0, 12, {4, 10, 0, 31, 4, 4, 4, 4, 4, 4, 4, 31, 0, 0}}, /* 206 */ - {0, 12, {0, 10, 0, 31, 4, 4, 4, 4, 4, 4, 4, 31, 0, 0}}, /* 207 */ - {0, 12, {0, 0, 60, 34, 33, 33, 113, 33, 33, 33, 34, 60, 0, 0}}, /* 208 */ - {0, 12, {10, 20, 0, 49, 41, 41, 41, 37, 37, 37, 35, 35, 0, 0}}, /* 209 */ - {0, 12, {16, 12, 0, 30, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 210 */ - {0, 12, {2, 12, 0, 30, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 211 */ - {0, 12, {12, 18, 0, 30, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 212 */ - {0, 12, {10, 20, 0, 30, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 213 */ - {0, 12, {0, 18, 0, 30, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 214 */ - {0, 12, {0, 0, 0, 0, 0, 65, 34, 20, 8, 20, 34, 65, 0, 0}}, /* 215 */ - {0, 12, {1, 1, 30, 35, 37, 37, 37, 41, 41, 41, 49, 30, 32, 32}}, /* 216 */ - {0, 12, {16, 12, 0, 33, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 217 */ - {0, 12, {2, 12, 0, 33, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 218 */ - {0, 12, {12, 18, 0, 33, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 219 */ - {0, 12, {0, 18, 0, 33, 33, 33, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 220 */ - {0, 12, {2, 12, 33, 33, 34, 18, 20, 12, 8, 8, 8, 8, 0, 0}}, /* 221 */ - {0, 12, {0, 0, 32, 32, 62, 33, 33, 33, 33, 62, 32, 32, 0, 0}}, /* 222 */ - {0, 12, {0, 0, 12, 18, 18, 18, 28, 18, 17, 17, 17, 62, 0, 0}}, /* 223 */ - {0, 12, {0, 16, 8, 4, 0, 30, 33, 7, 25, 33, 35, 29, 0, 0}}, /* 224 */ - {0, 12, {0, 2, 4, 8, 0, 30, 33, 7, 25, 33, 35, 29, 0, 0}}, /* 225 */ - {0, 12, {0, 0, 12, 18, 0, 30, 33, 7, 25, 33, 35, 29, 0, 0}}, /* 226 */ - {0, 12, {0, 0, 10, 20, 0, 30, 33, 7, 25, 33, 35, 29, 0, 0}}, /* 227 */ - {0, 12, {0, 0, 0, 18, 0, 30, 33, 7, 25, 33, 35, 29, 0, 0}}, /* 228 */ - {0, 12, {0, 8, 20, 8, 0, 30, 33, 7, 25, 33, 35, 29, 0, 0}}, /* 229 */ - {0, 12, {0, 0, 0, 0, 0, 62, 73, 25, 47, 72, 73, 62, 0, 0}}, /* 230 */ - {0, 12, {0, 0, 0, 0, 0, 30, 33, 32, 32, 32, 33, 30, 4, 8}}, /* 231 */ - {0, 12, {0, 16, 8, 4, 0, 30, 33, 33, 63, 32, 33, 30, 0, 0}}, /* 232 */ - {0, 12, {0, 2, 4, 8, 0, 30, 33, 33, 63, 32, 33, 30, 0, 0}}, /* 233 */ - {0, 12, {0, 0, 12, 18, 0, 30, 33, 33, 63, 32, 33, 30, 0, 0}}, /* 234 */ - {0, 12, {0, 0, 0, 18, 0, 30, 33, 33, 63, 32, 33, 30, 0, 0}}, /* 235 */ - {0, 12, {0, 16, 8, 4, 0, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 236 */ - {0, 12, {0, 4, 8, 16, 0, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 237 */ - {0, 12, {0, 0, 8, 20, 0, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 238 */ - {0, 12, {0, 0, 0, 20, 0, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 239 */ - {0, 12, {0, 20, 8, 20, 2, 30, 34, 34, 34, 34, 34, 28, 0, 0}}, /* 240 */ - {0, 12, {0, 0, 10, 20, 0, 46, 49, 33, 33, 33, 33, 33, 0, 0}}, /* 241 */ - {0, 12, {0, 16, 8, 4, 0, 30, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 242 */ - {0, 12, {0, 2, 4, 8, 0, 30, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 243 */ - {0, 12, {0, 0, 12, 18, 0, 30, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 244 */ - {0, 12, {0, 0, 10, 20, 0, 30, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 245 */ - {0, 12, {0, 0, 0, 18, 0, 30, 33, 33, 33, 33, 33, 30, 0, 0}}, /* 246 */ - {0, 12, {0, 0, 0, 0, 0, 0, 0, 24, 0, 126, 0, 24, 0, 0}}, /* 247 */ - {0, 12, {0, 0, 0, 1, 2, 30, 37, 37, 41, 41, 49, 30, 32, 32}}, /* 248 */ - {0, 12, {0, 0, 16, 8, 4, 33, 33, 33, 33, 33, 35, 29, 0, 0}}, /* 249 */ - {0, 12, {0, 0, 2, 4, 8, 33, 33, 33, 33, 33, 35, 29, 0, 0}}, /* 250 */ - {0, 12, {0, 0, 12, 18, 0, 33, 33, 33, 33, 33, 35, 29, 0, 0}}, /* 251 */ - {0, 12, {0, 0, 0, 18, 0, 33, 33, 33, 33, 33, 35, 29, 0, 0}}, /* 252 */ - {0, 12, {0, 0, 2, 4, 8, 33, 33, 17, 18, 10, 14, 4, 36, 24}}, /* 253 */ - {0, 12, {0, 0, 32, 32, 32, 46, 49, 33, 33, 33, 49, 46, 32, 32}}, /* 254 */ - {0, 12, {0, 0, 0, 18, 0, 33, 33, 17, 18, 10, 14, 4, 36, 24}} /* 255 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 0 */ + {0, 11, {0, 0, 0, 0, 0, 16, 56, 124, 56, 16, 0, 0, 0}}, /* 1 */ + {0, 11, {0, 84, 42, 84, 42, 84, 42, 84, 42, 84, 42, 84, 42}}, /* 2 */ + {0, 11, {0, 0, 72, 72, 120, 72, 72, 14, 4, 4, 4, 4, 0}}, /* 3 */ + {0, 11, {0, 0, 120, 64, 112, 64, 64, 30, 16, 28, 16, 16, 0}}, /* 4 */ + {0, 11, {0, 0, 56, 64, 64, 64, 56, 28, 18, 28, 20, 18, 0}}, /* 5 */ + {0, 11, {0, 0, 64, 64, 64, 64, 120, 30, 16, 28, 16, 16, 0}}, /* 6 */ + {0, 11, {0, 0, 56, 68, 68, 56, 0, 0, 0, 0, 0, 0, 0}}, /* 7 */ + {0, 11, {0, 0, 0, 16, 16, 124, 16, 16, 0, 124, 0, 0, 0}}, /* 8 */ + {0, 11, {0, 0, 72, 104, 88, 72, 72, 16, 16, 16, 16, 30, 0}}, /* 9 */ + {0, 11, {0, 0, 68, 68, 40, 40, 16, 62, 8, 8, 8, 8, 0}}, /* 10 */ + {0, 11, {8, 8, 8, 8, 8, 8, 120, 0, 0, 0, 0, 0, 0}}, /* 11 */ + {0, 11, {0, 0, 0, 0, 0, 0, 120, 8, 8, 8, 8, 8, 8}}, /* 12 */ + {0, 11, {0, 0, 0, 0, 0, 0, 15, 8, 8, 8, 8, 8, 8}}, /* 13 */ + {0, 11, {8, 8, 8, 8, 8, 8, 15, 0, 0, 0, 0, 0, 0}}, /* 14 */ + {0, 11, {8, 8, 8, 8, 8, 8, 127, 8, 8, 8, 8, 8, 8}}, /* 15 */ + {0, 11, {0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 16 */ + {0, 11, {0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 17 */ + {0, 11, {0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0}}, /* 18 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0}}, /* 19 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0}}, /* 20 */ + {0, 11, {8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8}}, /* 21 */ + {0, 11, {8, 8, 8, 8, 8, 8, 120, 8, 8, 8, 8, 8, 8}}, /* 22 */ + {0, 11, {8, 8, 8, 8, 8, 8, 127, 0, 0, 0, 0, 0, 0}}, /* 23 */ + {0, 11, {0, 0, 0, 0, 0, 0, 127, 8, 8, 8, 8, 8, 8}}, /* 24 */ + {0, 11, {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}}, /* 25 */ + {0, 11, {0, 0, 0, 2, 12, 48, 64, 48, 12, 2, 126, 0, 0}}, /* 26 */ + {0, 11, {0, 0, 0, 64, 48, 12, 2, 12, 48, 64, 126, 0, 0}}, /* 27 */ + {0, 11, {0, 0, 0, 0, 0, 126, 36, 36, 36, 36, 68, 0, 0}}, /* 28 */ + {0, 11, {0, 0, 0, 2, 4, 126, 8, 16, 126, 32, 64, 0, 0}}, /* 29 */ + {0, 11, {0, 0, 28, 34, 32, 32, 112, 32, 32, 34, 92, 0, 0}}, /* 30 */ + {0, 11, {0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0}}, /* 31 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 32 */ + {0, 11, {0, 0, 8, 8, 8, 8, 8, 8, 8, 0, 8, 0, 0}}, /* 33 */ + {0, 11, {0, 0, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 34 */ + {0, 11, {0, 0, 0, 20, 20, 62, 20, 62, 20, 20, 0, 0, 0}}, /* 35 */ + {0, 11, {0, 0, 0, 8, 30, 40, 28, 10, 60, 8, 0, 0, 0}}, /* 36 */ + {0, 11, {0, 0, 34, 82, 36, 8, 8, 16, 36, 74, 68, 0, 0}}, /* 37 */ + {0, 11, {0, 0, 0, 0, 48, 72, 72, 48, 74, 68, 58, 0, 0}}, /* 38 */ + {0, 11, {0, 0, 28, 24, 32, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 39 */ + {0, 11, {0, 0, 4, 8, 8, 16, 16, 16, 8, 8, 4, 0, 0}}, /* 40 */ + {0, 11, {0, 0, 16, 8, 8, 4, 4, 4, 8, 8, 16, 0, 0}}, /* 41 */ + {0, 11, {0, 0, 0, 0, 36, 24, 126, 24, 36, 0, 0, 0, 0}}, /* 42 */ + {0, 11, {0, 0, 0, 0, 8, 8, 62, 8, 8, 0, 0, 0, 0}}, /* 43 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 24, 32, 0}}, /* 44 */ + {0, 11, {0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0}}, /* 45 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 28, 8, 0}}, /* 46 */ + {0, 11, {0, 0, 2, 2, 4, 4, 8, 16, 16, 32, 32, 0, 0}}, /* 47 */ + {0, 11, {0, 0, 24, 36, 66, 66, 66, 66, 66, 36, 24, 0, 0}}, /* 48 */ + {0, 11, {0, 0, 8, 24, 40, 8, 8, 8, 8, 8, 62, 0, 0}}, /* 49 */ + {0, 11, {0, 0, 60, 66, 66, 2, 4, 24, 32, 64, 126, 0, 0}}, /* 50 */ + {0, 11, {0, 0, 126, 2, 4, 8, 28, 2, 2, 66, 60, 0, 0}}, /* 51 */ + {0, 11, {0, 0, 4, 12, 20, 36, 68, 68, 126, 4, 4, 0, 0}}, /* 52 */ + {0, 11, {0, 0, 126, 64, 64, 92, 98, 2, 2, 66, 60, 0, 0}}, /* 53 */ + {0, 11, {0, 0, 28, 32, 64, 64, 92, 98, 66, 66, 60, 0, 0}}, /* 54 */ + {0, 11, {0, 0, 126, 2, 4, 8, 8, 16, 16, 32, 32, 0, 0}}, /* 55 */ + {0, 11, {0, 0, 60, 66, 66, 66, 60, 66, 66, 66, 60, 0, 0}}, /* 56 */ + {0, 11, {0, 0, 60, 66, 66, 70, 58, 2, 2, 4, 56, 0, 0}}, /* 57 */ + {0, 11, {0, 0, 0, 0, 8, 28, 8, 0, 0, 8, 28, 8, 0}}, /* 58 */ + {0, 11, {0, 0, 0, 0, 8, 28, 8, 0, 0, 28, 24, 32, 0}}, /* 59 */ + {0, 11, {0, 0, 2, 4, 8, 16, 32, 16, 8, 4, 2, 0, 0}}, /* 60 */ + {0, 11, {0, 0, 0, 0, 0, 126, 0, 0, 126, 0, 0, 0, 0}}, /* 61 */ + {0, 11, {0, 0, 32, 16, 8, 4, 2, 4, 8, 16, 32, 0, 0}}, /* 62 */ + {0, 11, {0, 0, 60, 66, 66, 2, 4, 8, 8, 0, 8, 0, 0}}, /* 63 */ + {0, 11, {0, 0, 60, 66, 66, 78, 82, 86, 74, 64, 60, 0, 0}}, /* 64 */ + {0, 11, {0, 0, 24, 36, 66, 66, 66, 126, 66, 66, 66, 0, 0}}, /* 65 */ + {0, 11, {0, 0, 124, 34, 34, 34, 60, 34, 34, 34, 124, 0, 0}}, /* 66 */ + {0, 11, {0, 0, 60, 66, 64, 64, 64, 64, 64, 66, 60, 0, 0}}, /* 67 */ + {0, 11, {0, 0, 124, 34, 34, 34, 34, 34, 34, 34, 124, 0, 0}}, /* 68 */ + {0, 11, {0, 0, 126, 64, 64, 64, 120, 64, 64, 64, 126, 0, 0}}, /* 69 */ + {0, 11, {0, 0, 126, 64, 64, 64, 120, 64, 64, 64, 64, 0, 0}}, /* 70 */ + {0, 11, {0, 0, 60, 66, 64, 64, 64, 78, 66, 70, 58, 0, 0}}, /* 71 */ + {0, 11, {0, 0, 66, 66, 66, 66, 126, 66, 66, 66, 66, 0, 0}}, /* 72 */ + {0, 11, {0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0}}, /* 73 */ + {0, 11, {0, 0, 14, 4, 4, 4, 4, 4, 4, 68, 56, 0, 0}}, /* 74 */ + {0, 11, {0, 0, 66, 68, 72, 80, 96, 80, 72, 68, 66, 0, 0}}, /* 75 */ + {0, 11, {0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 126, 0, 0}}, /* 76 */ + {0, 11, {0, 0, 66, 102, 102, 90, 90, 66, 66, 66, 66, 0, 0}}, /* 77 */ + {0, 11, {0, 0, 66, 66, 98, 82, 74, 70, 66, 66, 66, 0, 0}}, /* 78 */ + {0, 11, {0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 79 */ + {0, 11, {0, 0, 124, 66, 66, 66, 124, 64, 64, 64, 64, 0, 0}}, /* 80 */ + {0, 11, {0, 0, 60, 66, 66, 66, 66, 66, 82, 74, 60, 2, 0}}, /* 81 */ + {0, 11, {0, 0, 124, 66, 66, 66, 124, 80, 72, 68, 66, 0, 0}}, /* 82 */ + {0, 11, {0, 0, 60, 66, 64, 64, 60, 2, 2, 66, 60, 0, 0}}, /* 83 */ + {0, 11, {0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0}}, /* 84 */ + {0, 11, {0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 85 */ + {0, 11, {0, 0, 66, 66, 66, 36, 36, 36, 24, 24, 24, 0, 0}}, /* 86 */ + {0, 11, {0, 0, 66, 66, 66, 66, 90, 90, 102, 102, 66, 0, 0}}, /* 87 */ + {0, 11, {0, 0, 66, 66, 36, 36, 24, 36, 36, 66, 66, 0, 0}}, /* 88 */ + {0, 11, {0, 0, 68, 68, 40, 40, 16, 16, 16, 16, 16, 0, 0}}, /* 89 */ + {0, 11, {0, 0, 126, 2, 4, 8, 24, 16, 32, 64, 126, 0, 0}}, /* 90 */ + {0, 11, {0, 0, 60, 32, 32, 32, 32, 32, 32, 32, 60, 0, 0}}, /* 91 */ + {0, 11, {0, 0, 32, 32, 16, 16, 8, 4, 4, 2, 2, 0, 0}}, /* 92 */ + {0, 11, {0, 0, 60, 4, 4, 4, 4, 4, 4, 4, 60, 0, 0}}, /* 93 */ + {0, 11, {0, 0, 8, 20, 34, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 94 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0}}, /* 95 */ + {0, 11, {0, 0, 56, 24, 4, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 96 */ + {0, 11, {0, 0, 0, 0, 0, 60, 2, 62, 66, 70, 58, 0, 0}}, /* 97 */ + {0, 11, {0, 0, 64, 64, 64, 92, 98, 66, 66, 98, 92, 0, 0}}, /* 98 */ + {0, 11, {0, 0, 0, 0, 0, 60, 66, 64, 64, 66, 60, 0, 0}}, /* 99 */ + {0, 11, {0, 0, 2, 2, 2, 58, 70, 66, 66, 70, 58, 0, 0}}, /* 100 */ + {0, 11, {0, 0, 0, 0, 0, 60, 66, 126, 64, 66, 60, 0, 0}}, /* 101 */ + {0, 11, {0, 0, 28, 34, 32, 32, 120, 32, 32, 32, 32, 0, 0}}, /* 102 */ + {0, 11, {0, 0, 0, 0, 0, 58, 68, 68, 56, 64, 60, 66, 60}}, /* 103 */ + {0, 11, {0, 0, 64, 64, 64, 92, 98, 66, 66, 66, 66, 0, 0}}, /* 104 */ + {0, 11, {0, 0, 0, 16, 0, 48, 16, 16, 16, 16, 124, 0, 0}}, /* 105 */ + {0, 11, {0, 0, 0, 4, 0, 12, 4, 4, 4, 4, 68, 68, 56}}, /* 106 */ + {0, 11, {0, 0, 64, 64, 64, 68, 72, 112, 72, 68, 66, 0, 0}}, /* 107 */ + {0, 11, {0, 0, 48, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0}}, /* 108 */ + {0, 11, {0, 0, 0, 0, 0, 104, 84, 84, 84, 84, 68, 0, 0}}, /* 109 */ + {0, 11, {0, 0, 0, 0, 0, 92, 98, 66, 66, 66, 66, 0, 0}}, /* 110 */ + {0, 11, {0, 0, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0}}, /* 111 */ + {0, 11, {0, 0, 0, 0, 0, 92, 98, 66, 98, 92, 64, 64, 64}}, /* 112 */ + {0, 11, {0, 0, 0, 0, 0, 58, 70, 66, 70, 58, 2, 2, 2}}, /* 113 */ + {0, 11, {0, 0, 0, 0, 0, 92, 34, 32, 32, 32, 32, 0, 0}}, /* 114 */ + {0, 11, {0, 0, 0, 0, 0, 60, 66, 48, 12, 66, 60, 0, 0}}, /* 115 */ + {0, 11, {0, 0, 0, 32, 32, 120, 32, 32, 32, 34, 28, 0, 0}}, /* 116 */ + {0, 11, {0, 0, 0, 0, 0, 66, 66, 66, 66, 70, 58, 0, 0}}, /* 117 */ + {0, 11, {0, 0, 0, 0, 0, 68, 68, 68, 40, 40, 16, 0, 0}}, /* 118 */ + {0, 11, {0, 0, 0, 0, 0, 68, 68, 84, 84, 84, 40, 0, 0}}, /* 119 */ + {0, 11, {0, 0, 0, 0, 0, 66, 36, 24, 24, 36, 66, 0, 0}}, /* 120 */ + {0, 11, {0, 0, 0, 0, 0, 66, 66, 66, 70, 58, 2, 66, 60}}, /* 121 */ + {0, 11, {0, 0, 0, 0, 0, 126, 4, 8, 16, 32, 126, 0, 0}}, /* 122 */ + {0, 11, {0, 0, 14, 16, 16, 8, 48, 8, 16, 16, 14, 0, 0}}, /* 123 */ + {0, 11, {0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 124 */ + {0, 11, {0, 0, 56, 4, 4, 8, 6, 8, 4, 4, 56, 0, 0}}, /* 125 */ + {0, 11, {0, 0, 18, 42, 36, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 126 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 127 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 128 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 129 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 130 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 131 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 132 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 133 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 134 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 135 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 136 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 137 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 138 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 139 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 140 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 141 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 142 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 143 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 144 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 145 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 146 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 147 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 148 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 149 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 150 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 151 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 152 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 153 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 154 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 155 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 156 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 157 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 158 */ + {0, 11, {0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0}}, /* 159 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 160 */ + {0, 11, {0, 0, 8, 0, 8, 8, 8, 8, 8, 8, 8, 0, 0}}, /* 161 */ + {0, 11, {0, 0, 8, 28, 42, 40, 40, 42, 28, 8, 0, 0, 0}}, /* 162 */ + {0, 11, {0, 0, 28, 34, 32, 32, 112, 32, 32, 34, 92, 0, 0}}, /* 163 */ + {0, 11, {0, 0, 0, 0, 66, 60, 36, 36, 60, 66, 0, 0, 0}}, /* 164 */ + {0, 11, {0, 0, 68, 68, 40, 40, 124, 16, 124, 16, 16, 0, 0}}, /* 165 */ + {0, 11, {0, 0, 8, 8, 8, 8, 0, 8, 8, 8, 8, 0, 0}}, /* 166 */ + {0, 11, {0, 24, 36, 32, 24, 36, 36, 24, 4, 36, 24, 0, 0}}, /* 167 */ + {0, 11, {0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 168 */ + {0, 11, {0, 60, 66, 90, 82, 82, 82, 90, 66, 60, 0, 0, 0}}, /* 169 */ + {0, 11, {0, 0, 28, 2, 30, 34, 30, 0, 62, 0, 0, 0, 0}}, /* 170 */ + {0, 11, {0, 0, 0, 10, 20, 40, 80, 40, 20, 10, 0, 0, 0}}, /* 171 */ + {0, 11, {0, 0, 0, 0, 0, 0, 62, 2, 2, 0, 0, 0, 0}}, /* 172 */ + {0, 11, {0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0}}, /* 173 */ + {0, 11, {0, 60, 66, 90, 86, 86, 90, 86, 66, 60, 0, 0, 0}}, /* 174 */ + {0, 11, {0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 175 */ + {0, 11, {0, 0, 24, 36, 36, 24, 0, 0, 0, 0, 0, 0, 0}}, /* 176 */ + {0, 11, {0, 0, 0, 8, 8, 62, 8, 8, 0, 62, 0, 0, 0}}, /* 177 */ + {0, 11, {0, 32, 80, 16, 32, 64, 112, 0, 0, 0, 0, 0, 0}}, /* 178 */ + {0, 11, {0, 112, 16, 32, 16, 80, 32, 0, 0, 0, 0, 0, 0}}, /* 179 */ + {0, 11, {0, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 180 */ + {0, 11, {0, 0, 0, 0, 0, 66, 66, 66, 66, 102, 90, 64, 0}}, /* 181 */ + {0, 11, {0, 0, 62, 116, 116, 116, 52, 20, 20, 20, 20, 0, 0}}, /* 182 */ + {0, 11, {0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0}}, /* 183 */ + {0, 11, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 16}}, /* 184 */ + {0, 11, {0, 32, 96, 32, 32, 32, 112, 0, 0, 0, 0, 0, 0}}, /* 185 */ + {0, 11, {0, 0, 24, 36, 36, 24, 0, 60, 0, 0, 0, 0, 0}}, /* 186 */ + {0, 11, {0, 0, 0, 80, 40, 20, 10, 20, 40, 80, 0, 0, 0}}, /* 187 */ + {0, 11, {0, 32, 96, 32, 32, 34, 118, 10, 10, 14, 2, 0, 0}}, /* 188 */ + {0, 11, {0, 32, 96, 32, 32, 36, 122, 2, 4, 8, 14, 0, 0}}, /* 189 */ + {0, 11, {0, 112, 16, 32, 16, 82, 38, 10, 10, 14, 2, 0, 0}}, /* 190 */ + {0, 11, {0, 0, 16, 0, 16, 16, 32, 64, 66, 66, 60, 0, 0}}, /* 191 */ + {0, 11, {0, 16, 8, 0, 24, 36, 66, 66, 126, 66, 66, 0, 0}}, /* 192 */ + {0, 11, {0, 8, 16, 0, 24, 36, 66, 66, 126, 66, 66, 0, 0}}, /* 193 */ + {0, 11, {0, 24, 36, 0, 24, 36, 66, 66, 126, 66, 66, 0, 0}}, /* 194 */ + {0, 11, {0, 20, 40, 0, 24, 36, 66, 66, 126, 66, 66, 0, 0}}, /* 195 */ + {0, 11, {0, 36, 36, 0, 24, 36, 66, 66, 126, 66, 66, 0, 0}}, /* 196 */ + {0, 11, {0, 24, 36, 24, 24, 36, 66, 66, 126, 66, 66, 0, 0}}, /* 197 */ + {0, 11, {0, 0, 46, 80, 80, 80, 92, 112, 80, 80, 94, 0, 0}}, /* 198 */ + {0, 11, {0, 0, 60, 66, 64, 64, 64, 64, 64, 66, 60, 8, 16}}, /* 199 */ + {0, 11, {0, 16, 8, 0, 126, 64, 64, 120, 64, 64, 126, 0, 0}}, /* 200 */ + {0, 11, {0, 8, 16, 0, 126, 64, 64, 120, 64, 64, 126, 0, 0}}, /* 201 */ + {0, 11, {0, 24, 36, 0, 126, 64, 64, 120, 64, 64, 126, 0, 0}}, /* 202 */ + {0, 11, {0, 36, 36, 0, 126, 64, 64, 120, 64, 64, 126, 0, 0}}, /* 203 */ + {0, 11, {0, 16, 8, 0, 62, 8, 8, 8, 8, 8, 62, 0, 0}}, /* 204 */ + {0, 11, {0, 8, 16, 0, 62, 8, 8, 8, 8, 8, 62, 0, 0}}, /* 205 */ + {0, 11, {0, 24, 36, 0, 62, 8, 8, 8, 8, 8, 62, 0, 0}}, /* 206 */ + {0, 11, {0, 20, 20, 0, 62, 8, 8, 8, 8, 8, 62, 0, 0}}, /* 207 */ + {0, 11, {0, 0, 124, 34, 34, 34, 114, 34, 34, 34, 124, 0, 0}}, /* 208 */ + {0, 11, {0, 20, 40, 0, 66, 98, 82, 82, 74, 70, 66, 0, 0}}, /* 209 */ + {0, 11, {0, 16, 8, 0, 60, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 210 */ + {0, 11, {0, 8, 16, 0, 60, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 211 */ + {0, 11, {0, 24, 36, 0, 60, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 212 */ + {0, 11, {0, 20, 40, 0, 60, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 213 */ + {0, 11, {0, 36, 36, 0, 60, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 214 */ + {0, 11, {0, 0, 0, 0, 66, 36, 24, 24, 36, 66, 0, 0, 0}}, /* 215 */ + {0, 11, {0, 2, 60, 70, 74, 74, 82, 82, 82, 98, 60, 64, 0}}, /* 216 */ + {0, 11, {0, 16, 8, 0, 66, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 217 */ + {0, 11, {0, 8, 16, 0, 66, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 218 */ + {0, 11, {0, 24, 36, 0, 66, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 219 */ + {0, 11, {0, 36, 36, 0, 66, 66, 66, 66, 66, 66, 60, 0, 0}}, /* 220 */ + {0, 11, {0, 8, 16, 0, 34, 34, 20, 8, 8, 8, 8, 0, 0}}, /* 221 */ + {0, 11, {0, 0, 64, 124, 66, 66, 66, 124, 64, 64, 64, 0, 0}}, /* 222 */ + {0, 11, {0, 0, 0, 60, 66, 66, 124, 66, 66, 98, 92, 64, 0}}, /* 223 */ + {0, 11, {0, 16, 8, 0, 0, 60, 2, 62, 66, 70, 58, 0, 0}}, /* 224 */ + {0, 11, {0, 8, 16, 0, 0, 60, 2, 62, 66, 70, 58, 0, 0}}, /* 225 */ + {0, 11, {0, 24, 36, 0, 0, 60, 2, 62, 66, 70, 58, 0, 0}}, /* 226 */ + {0, 11, {0, 20, 40, 0, 0, 60, 2, 62, 66, 70, 58, 0, 0}}, /* 227 */ + {0, 11, {0, 36, 36, 0, 0, 60, 2, 62, 66, 70, 58, 0, 0}}, /* 228 */ + {0, 11, {0, 24, 36, 24, 0, 60, 2, 62, 66, 70, 58, 0, 0}}, /* 229 */ + {0, 11, {0, 0, 0, 0, 0, 52, 10, 62, 72, 74, 52, 0, 0}}, /* 230 */ + {0, 11, {0, 0, 0, 0, 0, 60, 66, 64, 64, 66, 60, 8, 16}}, /* 231 */ + {0, 11, {0, 16, 8, 0, 0, 60, 66, 126, 64, 66, 60, 0, 0}}, /* 232 */ + {0, 11, {0, 8, 16, 0, 0, 60, 66, 126, 64, 66, 60, 0, 0}}, /* 233 */ + {0, 11, {0, 24, 36, 0, 0, 60, 66, 126, 64, 66, 60, 0, 0}}, /* 234 */ + {0, 11, {0, 36, 36, 0, 0, 60, 66, 126, 64, 66, 60, 0, 0}}, /* 235 */ + {0, 11, {0, 16, 8, 0, 0, 24, 8, 8, 8, 8, 62, 0, 0}}, /* 236 */ + {0, 11, {0, 8, 16, 0, 0, 24, 8, 8, 8, 8, 62, 0, 0}}, /* 237 */ + {0, 11, {0, 24, 36, 0, 0, 24, 8, 8, 8, 8, 62, 0, 0}}, /* 238 */ + {0, 11, {0, 36, 36, 0, 0, 24, 8, 8, 8, 8, 62, 0, 0}}, /* 239 */ + {0, 11, {0, 36, 24, 40, 4, 60, 66, 66, 66, 66, 60, 0, 0}}, /* 240 */ + {0, 11, {0, 20, 40, 0, 0, 92, 98, 66, 66, 66, 66, 0, 0}}, /* 241 */ + {0, 11, {0, 16, 8, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0}}, /* 242 */ + {0, 11, {0, 8, 16, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0}}, /* 243 */ + {0, 11, {0, 24, 36, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0}}, /* 244 */ + {0, 11, {0, 20, 40, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0}}, /* 245 */ + {0, 11, {0, 36, 36, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0}}, /* 246 */ + {0, 11, {0, 0, 0, 8, 8, 0, 62, 0, 8, 8, 0, 0, 0}}, /* 247 */ + {0, 11, {0, 0, 0, 0, 2, 60, 70, 74, 82, 98, 60, 64, 0}}, /* 248 */ + {0, 11, {0, 16, 8, 0, 0, 66, 66, 66, 66, 70, 58, 0, 0}}, /* 249 */ + {0, 11, {0, 8, 16, 0, 0, 66, 66, 66, 66, 70, 58, 0, 0}}, /* 250 */ + {0, 11, {0, 24, 36, 0, 0, 66, 66, 66, 66, 70, 58, 0, 0}}, /* 251 */ + {0, 11, {0, 36, 36, 0, 0, 66, 66, 66, 66, 70, 58, 0, 0}}, /* 252 */ + {0, 11, {0, 8, 16, 0, 0, 66, 66, 66, 70, 58, 2, 66, 60}}, /* 253 */ + {0, 11, {0, 0, 0, 64, 64, 92, 98, 66, 66, 98, 92, 64, 64}}, /* 254 */ + {0, 11, {0, 36, 36, 0, 0, 66, 66, 66, 70, 58, 2, 66, 60}} /* 255 */ }; diff --git a/src/text/text.c b/src/text/text.c index 2bb89b6..45e5886 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -12,7 +12,7 @@ void (*MwFLFontFree)(void* handle) = NULL; #endif #define FontWidth 7 -#define FontHeight 14 +#define FontHeight 13 static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, MwLLColor color); @@ -240,7 +240,7 @@ int MwTextHeight(MwWidget handle, MwFLFont ttf, const char* text) { void* MwFontLoad(unsigned char* data, unsigned int size) { if(MwFLFontLoad) - return MwFLFontLoad(data, size, 14); + return MwFLFontLoad(data, size, 13); return NULL; } From 421cf1557426d9014f4593e96d08544542da43d1 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 03:50:13 +0900 Subject: [PATCH 069/168] fix --- src/abstract/directory.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/abstract/directory.c b/src/abstract/directory.c index d7b364f..63146b1 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -206,11 +206,13 @@ static void MwDirectoryJoinSingle(char* target, char* p) { } char* MwDirectoryJoin(char* a, char* b) { - char* p = MwStringDuplicate(a); + char* p = malloc(strlen(a) + 3 + strlen(b)); char* bdup = MwStringDuplicate(b); char* b2 = bdup; int i; + strcpy(p, a); + for(i = strlen(p) - 1; i >= 0; i--) { if(p[i] == DIRSEP) { p[i] = 0; From cf0eda33f2dcf7fe54dc4b13ec64f33dc2466626 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 04:24:11 +0900 Subject: [PATCH 070/168] ok --- src/default.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/default.c b/src/default.c index baeeb67..2cb1633 100644 --- a/src/default.c +++ b/src/default.c @@ -1,8 +1,8 @@ #include -// #define USE_CATPPUCCIN +#define USE_CATPPUCCIN_DARK -#ifdef USE_CATPPUCCIN +#ifdef USE_CATPPUCCIN_LIGHT const char* MwDefaultBackground = "#eff1f5"; const char* MwDefaultForeground = "#4c4f69"; const char* MwDefaultSubBackground = "#9ca0b0"; @@ -18,7 +18,7 @@ const char* MwDefaultTitleBackground = "#008"; const char* MwDefaultTitleForeground = "#fff"; #endif -#ifdef USE_CATPPUCCIN +#ifdef USE_CATPPUCCIN_DARK const char* MwDefaultDarkBackground = "#1e1e2e"; const char* MwDefaultDarkForeground = "#cdd6f4"; const char* MwDefaultDarkSubBackground = "#313244"; From 9f3332766f8a9b5712c788ddc3b230de822c6c7e Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 04:42:13 +0900 Subject: [PATCH 071/168] limit --- src/widget/clock.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widget/clock.c b/src/widget/clock.c index 547464a..70471c6 100644 --- a/src/widget/clock.c +++ b/src/widget/clock.c @@ -22,6 +22,8 @@ static void hand(MwWidget handle, double x, double y, double width, double lengt double c3 = cos(rad - M_PI); double s3 = sin(rad - M_PI); + if(width < width / 10) width = width / 10; + p[0].x = c2 * width / 2; p[0].y = s2 * width / 2; @@ -42,6 +44,7 @@ static void hand(MwWidget handle, double x, double y, double width, double lengt p[4] = p[0]; MwLLPolygon(handle->lowlevel, p, 4, inside); + MwLLLine(handle->lowlevel, &p[0], border); MwLLLine(handle->lowlevel, &p[1], border); MwLLLine(handle->lowlevel, &p[2], border); From a2ae35c794be6509eae858e7f793bb8d5f1f1d7c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 13 Sep 2026 12:57:41 -0700 Subject: [PATCH 072/168] wayland: don't force render if buffer isn't configured --- src/backend/wayland/wayland.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 3c2d9bd..49b6019 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1610,6 +1610,11 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { static void MwLLForceRenderImpl(MwLL handle) { WIDGET_CHECK(handle); + + if(!handle->wayland.configured) { + return; + } + wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); handle->wayland.force_render = MwTRUE; From 9c4dd06fa405dc9e820abf051b20f09fa8669ff5 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 13 Sep 2026 13:04:41 -0700 Subject: [PATCH 073/168] roundtrip before and after destroying a widget --- src/backend/wayland/wayland.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 49b6019..958d9ef 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -734,6 +734,12 @@ static void destroy_widget(MwLL handle) { MwLLShow(handle, MwFALSE); + if(wl_display_roundtrip(handle->wayland.display) == -1) { + printf("roundtrip failed\n"); + raise(SIGTRAP); + return; + } + switch(handle->wayland.type) { case MwLL_WAYLAND_TOPLEVEL: destroy_toplevel(handle); From 6e0bbc33b977bb36a182d7dcc8921239431b3ebd Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 13 Sep 2026 14:02:40 -0700 Subject: [PATCH 074/168] =?UTF-8?q?=F0=9F=A6=80=F0=9F=A6=80=F0=9F=A6=80=20?= =?UTF-8?q?DESTROYED=20TABLE=20MUTEX=20IS=20GONE=20=F0=9F=A6=80?= =?UTF-8?q?=F0=9F=A6=80=F0=9F=A6=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Mw/LowLevel/Wayland.h | 16 +----- src/backend/wayland/interfaces.c | 57 +++++++++++++----- src/backend/wayland/wayland.c | 99 ++++++-------------------------- 3 files changed, 63 insertions(+), 109 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 3e9d671..305f8bc 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -500,10 +500,6 @@ int MwLLWaylandHyprlandGetRoundness(void); void MwLLWaylandHangUntilConfigured(MwLL handle); -MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); -void MwLLWaylandWidgetUndestroy(MwLL self); -void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)); - /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland); @@ -515,18 +511,10 @@ void MwLLWaylandFlush(MwLL handle); void MwLLWaylandCascadeChildren(MwLL handle); /* Standard procedure before event callbacks in Wayland */ -#define WAYLAND_EVENT_OP_START(self) \ - if(MwLLWaylandWidgetIsDestroyed(self)) { \ - return; \ - } +#define WAYLAND_EVENT_OP_START(self) pthread_mutex_lock(&self->wayland.eventsMutex); /* Footer for WAYLAND_EVENT_OP_START */ -#define WAYLAND_EVENT_OP_END(self) - -#define WIDGET_CHECK(handle) \ - if(!handle->wayland.valid) { \ - return; \ - } +#define WAYLAND_EVENT_OP_END(self) pthread_mutex_unlock(&self->wayland.eventsMutex); /* the two decoration manager constructs */ typedef struct zxdg_decoration_manager_v1_context { diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 0ab3f43..247919c 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -720,8 +720,7 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri MwLL self = data; MwMouse p; MwLL topmost_parent = self; - int i; - MwBool inArea = MwFALSE; + MwBool inArea = MwFALSE; (void)wl_pointer; (void)serial; @@ -753,9 +752,7 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri } self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; - for(i = 0; i < arrlen(self->wayland.currentlyHeldWidgets); i++) { - arrdel(self->wayland.currentlyHeldWidgets, i); - } + arrsetlen(self->wayland.currentlyHeldWidgets, 0); mouse_dispatch(self, p, state); } if(self->wayland.backbuffer.surface) { @@ -1092,21 +1089,30 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, WAYLAND_EVENT_OP_START(self); + /* Always remember the seat itself, regardless of which capabilities it has - this is + * both what setup_clipboard()/setup_zwp_clipboard() below use, and what lets + * wl_seat_interface_destroy() release it later even on a keyboard-only seat. */ + self->wayland.pointer_seat = wl_seat; + if(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { self->wayland.keyboard = wl_seat_get_keyboard(wl_seat); wl_keyboard_add_listener(self->wayland.keyboard, &keyboard_listener, data); } if(capabilities & WL_SEAT_CAPABILITY_POINTER) { - self->wayland.pointer_seat = wl_seat; - self->wayland.pointer = wl_seat_get_pointer(wl_seat); + self->wayland.pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data); } WAYLAND_EVENT_OP_END(self); - if(self->wayland.clipboard_manager.wl) - setup_clipboard(self, self->wayland.pointer_seat); - if(self->wayland.clipboard_manager.zwp) - setup_zwp_clipboard(self, self->wayland.pointer_seat); + /* Only hooked up if this seat actually has a pointer: wl_data_device.get_data_device() + * requires a non-null seat, and pointer_seat is only ever null before the first + * capabilities event has arrived at all. */ + if(capabilities & WL_SEAT_CAPABILITY_POINTER) { + if(self->wayland.clipboard_manager.wl) + setup_clipboard(self, self->wayland.pointer_seat); + if(self->wayland.clipboard_manager.zwp) + setup_zwp_clipboard(self, self->wayland.pointer_seat); + } }; static void output_geometry(void* data, @@ -1160,8 +1166,9 @@ void xdg_wm_base_ping(void* data, /* wl_seat setup function */ static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); - MwU32 ver = (version >= 4) ? 4 : 1; + MwU32 ver = (version >= 4) ? 4 : 1; /* version 4 needed for wl_seat_release */ proto->listener = malloc(sizeof(struct wl_seat_listener)); + proto->context = NULL; ((struct wl_seat_listener*)proto->listener)->name = wl_seat_name; ((struct wl_seat_listener*)proto->listener)->capabilities = wl_seat_capabilities; @@ -1172,7 +1179,31 @@ static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll, MwU32 version) { } static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; + if(wayland->pointer != NULL) { + if(wl_proxy_get_version((struct wl_proxy*)wayland->pointer) >= WL_POINTER_RELEASE_SINCE_VERSION) { + wl_pointer_release(wayland->pointer); + } else { + wl_pointer_destroy(wayland->pointer); + } + wayland->pointer = NULL; + } + if(wayland->keyboard != NULL) { + if(wl_proxy_get_version((struct wl_proxy*)wayland->keyboard) >= WL_KEYBOARD_RELEASE_SINCE_VERSION) { + wl_keyboard_release(wayland->keyboard); + } else { + wl_keyboard_destroy(wayland->keyboard); + } + wayland->keyboard = NULL; + } + if(wayland->pointer_seat != NULL) { + if(wl_proxy_get_version((struct wl_proxy*)wayland->pointer_seat) >= WL_SEAT_RELEASE_SINCE_VERSION) { + wl_seat_release(wayland->pointer_seat); + } else { + wl_seat_destroy(wayland->pointer_seat); + } + wayland->pointer_seat = NULL; + } + free(data->listener); free(data); } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 958d9ef..7253c00 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -12,39 +12,6 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; -static pthread_mutex_t destroyedWidgetsTableMutex; -/* - * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. - * - * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. - */ -static MwLL* destroyedWidgetsTable; - -MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { - int i; - pthread_mutex_lock(&destroyedWidgetsTableMutex); - for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { - if(self == destroyedWidgetsTable[i]) { - pthread_mutex_unlock(&destroyedWidgetsTableMutex); - return MwTRUE; - } - } - pthread_mutex_unlock(&destroyedWidgetsTableMutex); - return MwFALSE; -} -void MwLLWaylandWidgetUndestroy(MwLL self) { - int i; - pthread_mutex_lock(&destroyedWidgetsTableMutex); - for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { - if(self == destroyedWidgetsTable[i]) { - arrdel(destroyedWidgetsTable, i); - break; - } - } - pthread_mutex_unlock(&destroyedWidgetsTableMutex); - return; -} - void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { if(handle->common.user) { MwWidget w = handle->common.user; @@ -76,7 +43,6 @@ static void recursive_dispatch_resize(MwLL handle) { static void recursive_render(MwLL handle) { int i; - WIDGET_CHECK(handle); for(i = 0; i < arrlen(((MwWidget)handle->common.user)->children); i++) recursive_render(((MwWidget)handle->common.user)->children[i]->lowlevel); @@ -386,8 +352,9 @@ static void destroy_toplevel(MwLL r) { xkb_context_unref(r->wayland.xkb_context); - wl_pointer_destroy(r->wayland.pointer); - wl_keyboard_destroy(r->wayland.keyboard); + /* wl_pointer/wl_keyboard/wl_seat are torn down centrally in wl_seat_interface_destroy, + * after this function returns, so every widget type that binds a seat (toplevel, popup, + * layer surface) releases them the same way instead of leaking or double-freeing them. */ MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); MwLLWaylandFifoSurfaceDestroy(&r->wayland.backbuffer); @@ -883,12 +850,7 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.x = x; r->wayland.y = y; r->wayland.parent = parent; - if(MwLLWaylandWidgetIsDestroyed(parent)) { - r->wayland.valid = MwFALSE; - return; - } else { - r->wayland.valid = MwTRUE; - } + r->wayland.valid = MwTRUE; if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { @@ -925,8 +887,6 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh } } - WIDGET_CHECK(r); - r->wayland.region = wl_compositor_create_region(r->wayland.compositor); r->wayland.o_region = wl_compositor_create_region(r->wayland.compositor); MwLLWaylandRegionSetup(r); @@ -1025,12 +985,9 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); memset(r, 0, sizeof(*r)); + pthread_mutex_init(&r->wayland.eventsMutex, NULL); MwLLCreateCommon(r); - if(MwLLWaylandWidgetIsDestroyed(r)) { - MwLLWaylandWidgetUndestroy(r); - } - r->wayland.is_toplevel = parent == NULL; r->wayland.is_clipping = 0; @@ -1067,8 +1024,6 @@ static void MwLLDestroyImpl(MwLL handle) { select_ret = select(1, NULL, NULL, NULL, &tv); } while((select_ret == -1) && (errno == EINTR)); - pthread_mutex_destroy(&handle->wayland.eventsMutex); - #ifdef USE_DBUS if(!wl_call_tbl.has_dbus) { MwLLDBusFreeContext(&wl_call_tbl.dbus, &handle->wayland.dbus); @@ -1094,9 +1049,7 @@ static void MwLLDestroyImpl(MwLL handle) { printf("widget invalid\n"); } - pthread_mutex_lock(&destroyedWidgetsTableMutex); - arrput(destroyedWidgetsTable, handle); - pthread_mutex_unlock(&destroyedWidgetsTableMutex); + pthread_mutex_destroy(&handle->wayland.eventsMutex); free(handle); } @@ -1116,7 +1069,7 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - WIDGET_CHECK(handle); + MwLLWaylandRegionInvalidate(handle); if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) { @@ -1181,7 +1134,6 @@ static void actually_set_wh(MwLL handle) { } static void MwLLSetWHImpl(MwLL handle, int w, int h) { - WIDGET_CHECK(handle); if(handle->wayland.ww == w && handle->wayland.wh == h) { return; @@ -1219,7 +1171,7 @@ const float_color one = {.2627451, .37254902, .49411765}; const float_color two = {.05490196, .17254902, .30588235}; static void MwLLBeginDrawImpl(MwLL handle) { - WIDGET_CHECK(handle); + cairo_save(handle->wayland.cairo.front_cairo); cairo_set_source_rgba(handle->wayland.cairo.front_cairo, 0, 0, 0, 0); cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_SOURCE); @@ -1373,7 +1325,6 @@ static void MwLLEndDrawImpl(MwLL handle) { } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - WIDGET_CHECK(handle); clip(handle); @@ -1384,7 +1335,6 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { int i; - WIDGET_CHECK(handle); clip(handle); @@ -1426,10 +1376,6 @@ static int MwLLPendingImpl(MwLL handle) { }; int pending = 0; - if(MwLLWaylandWidgetIsDestroyed(handle) || !handle->wayland.valid) { - return 0; - } - handle->wayland.resizing = 0; if(handle->wayland.setting_wh) { @@ -1502,7 +1448,6 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - WIDGET_CHECK(handle); if(!MwWaylandVulkan) { if(handle->wayland.did_event_loop_early) { @@ -1525,7 +1470,7 @@ static void MwLLNextEventImpl(MwLL handle) { } static void MwLLSetTitleImpl(MwLL handle, const char* title) { - WIDGET_CHECK(handle); + if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { xdg_toplevel_set_title(handle->wayland.toplevel->xdg_top_level, title); } @@ -1551,7 +1496,6 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { } static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - WIDGET_CHECK(handle); clip(handle); @@ -1561,7 +1505,7 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { - WIDGET_CHECK(handle); + if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { if(WAYLAND_GET_INTERFACE(handle->wayland, xdg_toplevel_icon_manager_v1) != NULL) { struct xdg_toplevel_icon_manager_v1* icon_manager = WAYLAND_GET_INTERFACE(handle->wayland, xdg_toplevel_icon_manager_v1)->context; @@ -1615,7 +1559,6 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { } static void MwLLForceRenderImpl(MwLL handle) { - WIDGET_CHECK(handle); if(!handle->wayland.configured) { return; @@ -1632,8 +1575,6 @@ static void MwLLForceRenderImpl(MwLL handle) { static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { int x, y, xs, ys; - WIDGET_CHECK(handle); - if(handle->wayland.cursor.setup) { MwLLWaylandBufferDestroy(&handle->wayland.cursor); wl_surface_destroy(handle->wayland.cursor.surface); @@ -1684,7 +1625,7 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { static void MwLLDetachImpl(MwLL handle, MwPoint* point) { MwLL p = handle->wayland.parent; int x = 0, y = 0; - WIDGET_CHECK(handle); + while(p != NULL) { if(p->wayland.type != MwLL_WAYLAND_TOPLEVEL) { x += p->wayland.x; @@ -1706,7 +1647,7 @@ static void MwLLShowImpl(MwLL handle, int show) { if(!handle->wayland.configured) { return; } - WIDGET_CHECK(handle); + /* Some guy on a mailing list said that "abusing" wl_surface_attach for this purpose is bad? This is documented behavior so please I beg of you let me know if there's a compositor that actually has a problem with this. */ if(handle->wayland.framebuffer.surface) { wl_surface_attach(handle->wayland.framebuffer.surface, show ? handle->wayland.framebuffer.shm_buffer : NULL, 0, 0); @@ -1725,7 +1666,7 @@ static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { } static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) { - WIDGET_CHECK(handle); + if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { xdg_toplevel_set_min_size(handle->wayland.toplevel->xdg_top_level, minx, miny); xdg_toplevel_set_max_size(handle->wayland.toplevel->xdg_top_level, maxx, maxy); @@ -1736,7 +1677,7 @@ static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { - WIDGET_CHECK(handle); + if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { if(WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1) != NULL) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1)->context; @@ -1763,7 +1704,7 @@ static void MwLLFocusImpl(MwLL handle) { static void MwLLGrabPointerImpl(MwLL handle, int toggle) { MwLL topmost_parent = handle; - WIDGET_CHECK(handle); + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; if(handle->wayland.pointer_constraints && handle->wayland.relative_pointer_manager) { if(toggle) { @@ -1790,7 +1731,6 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) { static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) { int i; - WIDGET_CHECK(handle); if(handle->wayland.clipboard_buffer != NULL) { free(handle->wayland.clipboard_buffer); @@ -1817,7 +1757,7 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_ty static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) { int i; - WIDGET_CHECK(handle); + if(clipboard_type == MwCLIPBOARD_PRIMARY) { if(handle->wayland.supports_zwp) { for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) { @@ -1839,8 +1779,6 @@ static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) { static void MwLLMakeToolWindowImpl(MwLL handle) { MwBool can_do_layer_surface = MwFALSE; - WIDGET_CHECK(handle); - can_do_layer_surface = (WAYLAND_GET_INTERFACE(handle->wayland, zwlr_layer_shell_v1) != NULL); if(!handle->wayland.parent && can_do_layer_surface) { @@ -1855,14 +1793,12 @@ static void MwLLMakeToolWindowImpl(MwLL handle) { static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { MwLL topmost_parent = handle; - WIDGET_CHECK(handle); while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; *point = topmost_parent->wayland.cur_mouse_pos; } static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { - WIDGET_CHECK(handle); rect->x = 0; rect->y = 0; @@ -1882,7 +1818,6 @@ static void MwLLBeginStateChangeImpl(MwLL handle) { static void MwLLEndStateChangeImpl(MwLL handle) { MwLL topmost_parent; int x, y; - WIDGET_CHECK(handle); if(!handle->wayland.changing) { return; @@ -1942,7 +1877,7 @@ static MwBool MwLLDoModernImpl(MwLL handle) { static void MwLLRaiseImpl(MwLL handle) { (void)handle; - /* WIDGET_CHECK(handle); + /* if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL) { MwLL topmost_parent = handle; From d8886d6860069db36786baf0cf69882477a477ac Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 13 Sep 2026 14:04:34 -0700 Subject: [PATCH 075/168] remove unnecessary mutex locks --- include/Mw/LowLevel/Wayland.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 305f8bc..b9cbf52 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -511,10 +511,10 @@ void MwLLWaylandFlush(MwLL handle); void MwLLWaylandCascadeChildren(MwLL handle); /* Standard procedure before event callbacks in Wayland */ -#define WAYLAND_EVENT_OP_START(self) pthread_mutex_lock(&self->wayland.eventsMutex); +#define WAYLAND_EVENT_OP_START(self) /* Footer for WAYLAND_EVENT_OP_START */ -#define WAYLAND_EVENT_OP_END(self) pthread_mutex_unlock(&self->wayland.eventsMutex); +#define WAYLAND_EVENT_OP_END(self) /* the two decoration manager constructs */ typedef struct zxdg_decoration_manager_v1_context { From 12483e997841af289986d3d9b547fe2d6ab28631 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 06:01:54 +0900 Subject: [PATCH 076/168] pie graph --- examples/basic/periodic.c | 2 +- include/Mw/Constants.h | 1 + milsko.xml | 1 + src/widget/chart.c | 55 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index c17cfd0..e53d66b 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -269,7 +269,7 @@ int main() { wclock = child(f); f = frame("Chart", -PaddingContent, -PaddingContent, MwChartClass, - MwNtype, MwCHART_3D_BAR, + MwNtype, MwCHART_PIE, MwNcolumnSpan, 2, NULL); w = child(f); diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index 6df447d..42f1471 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -116,6 +116,7 @@ enum MwCLIPBOARD { enum MwCHART { MwCHART_BAR = 0, MwCHART_3D_BAR, + MwCHART_PIE }; enum MwMOUSE { diff --git a/milsko.xml b/milsko.xml index 6bf802b..0652a55 100644 --- a/milsko.xml +++ b/milsko.xml @@ -233,6 +233,7 @@ 0 + 1 diff --git a/src/widget/chart.c b/src/widget/chart.c index 83e3a5e..4079e8b 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -13,6 +13,7 @@ static const char* palette0[] = { NULL}; #define NUMFMT "%.2f" +#define PIE_DIV 4 static int wcreate(MwWidget handle) { MwChart c = malloc(sizeof(*c)); @@ -239,6 +240,60 @@ static void draw(MwWidget handle) { MwLLFreeColor(colorl); MwLLFreeColor(color); } + } else if(type == MwCHART_PIE) { + double sum = 0; + int radius = r.width < r.height ? r.width : r.height; + double cangle = 0; + int k; + + for(i = 0; i < arrlen(c->entries); i++) { + if(c->entries[i].value > 0) sum += c->entries[i].value; + } + + for(k = 0; k < 2; k++) { + for(i = 0; i < arrlen(c->entries); i++) { + MwLLColor color; + double angle = c->entries[i].value / sum * 360; + MwPoint p[360 + 1 + 1]; + int div = angle / PIE_DIV; + int j; + int count; + + if(c->entries[i].value <= 0) continue; + + color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + + p[0].x = r.width / 2; + p[0].y = r.height / 2; + for(j = 0; j <= div; j++) { + double a = angle / div * j; + + p[div - j + 1].x = p[0].x + cos((cangle + a - 90) / 180 * M_PI) * radius / 2; + p[div - j + 1].y = p[0].y + sin((cangle + a - 90) / 180 * M_PI) * radius / 2; + } + + count = j + 1; + + if(k == 0) { + MwLLPolygon(handle->lowlevel, p, count, color); + } else { + int j; + + p[count] = p[0]; + for(j = 0; j < count; j++) { + MwLLLine(handle->lowlevel, &p[j], border); + } + + p[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; + p[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; + MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); + } + + cangle += angle; + + MwLLFreeColor(color); + } + } } MwLLFreeColor(border); From d2cbe88cb3e4c0314945a5305ccc087fd2ca3b41 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 06:59:15 +0900 Subject: [PATCH 077/168] 3d pie --- examples/basic/periodic.c | 18 ++++++-- include/Mw/Constants.h | 3 +- milsko.xml | 1 + src/widget/chart.c | 94 +++++++++++++++++++++++++++++---------- 4 files changed, 88 insertions(+), 28 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index e53d66b..adaf35b 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -268,9 +268,8 @@ int main() { f = frame("Clock", -PaddingContent, -PaddingContent, MwClockClass, NULL); wclock = child(f); - f = frame("Chart", -PaddingContent, -PaddingContent, MwChartClass, - MwNtype, MwCHART_PIE, - MwNcolumnSpan, 2, + f = frame("3D Bar Chart", -PaddingContent, -PaddingContent, MwChartClass, + MwNtype, MwCHART_3D_BAR, NULL); w = child(f); MwChartAdd(w, -1, "A", -800, NULL); @@ -282,6 +281,19 @@ int main() { MwChartAdd(w, -1, "G", 400, NULL); MwChartAdd(w, -1, "H", 800, NULL); + f = frame("3D Pie Chart", -PaddingContent, -PaddingContent, MwChartClass, + MwNtype, MwCHART_3D_PIE, + NULL); + w = child(f); + MwChartAdd(w, -1, "A", 10, NULL); + MwChartAdd(w, -1, "B", 20, NULL); + MwChartAdd(w, -1, "C", 30, NULL); + MwChartAdd(w, -1, "D", 10, NULL); + MwChartAdd(w, -1, "E", 20, NULL); + MwChartAdd(w, -1, "F", 30, NULL); + MwChartAdd(w, -1, "G", 10, NULL); + MwChartAdd(w, -1, "H", 20, NULL); + f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL); w = child(f); MwComboBoxAdd(w, -1, "Hello!"); diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index 42f1471..6379fef 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -116,7 +116,8 @@ enum MwCLIPBOARD { enum MwCHART { MwCHART_BAR = 0, MwCHART_3D_BAR, - MwCHART_PIE + MwCHART_PIE, + MwCHART_3D_PIE }; enum MwMOUSE { diff --git a/milsko.xml b/milsko.xml index 0652a55..084f825 100644 --- a/milsko.xml +++ b/milsko.xml @@ -234,6 +234,7 @@ 0 + 1 diff --git a/src/widget/chart.c b/src/widget/chart.c index 4079e8b..9c87e3f 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -13,7 +13,7 @@ static const char* palette0[] = { NULL}; #define NUMFMT "%.2f" -#define PIE_DIV 4 +#define PIE_DIV 10 static int wcreate(MwWidget handle) { MwChart c = malloc(sizeof(*c)); @@ -63,8 +63,9 @@ static void draw_line(MwWidget handle, const char* text, double x, double y, dou } static void draw(MwWidget handle) { - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNforeground)); + int ColorDiff = MwGetColorDifference(handle); + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNforeground)); MwRect r; MwChart c = handle->internal; int i; @@ -77,7 +78,8 @@ static void draw(MwWidget handle) { double vmax = -0xffffffff; int space = MwTextHeight(handle, NULL, "M"); MwPoint p[2]; - int type = MwGetInteger(handle, MwNtype); + int type = MwGetInteger(handle, MwNtype); + int modern = MwGetInteger(handle, MwNmodernLook); for(n = 0; colors[n] != NULL; n++); @@ -157,10 +159,9 @@ static void draw(MwWidget handle) { node.width = width; for(i = 0; i < arrlen(c->entries); i++) { - int ColorDiff = MwGetColorDifference(handle); - MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); - MwLLColor colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); - MwLLColor colord = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); + MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + MwLLColor colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); + MwLLColor colord = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); MwPoint persp_top[5]; MwPoint persp_right[5]; @@ -213,7 +214,7 @@ static void draw(MwWidget handle) { MwLLPolygon(handle->lowlevel, persp_right, 4, colord); } - if(!MwGetInteger(handle, MwNmodernLook)) { + if(!modern) { MwDrawRectLine(handle, &node, border); if(type == MwCHART_3D_BAR) { @@ -240,28 +241,32 @@ static void draw(MwWidget handle) { MwLLFreeColor(colorl); MwLLFreeColor(color); } - } else if(type == MwCHART_PIE) { - double sum = 0; - int radius = r.width < r.height ? r.width : r.height; - double cangle = 0; - int k; + } else if(type == MwCHART_PIE || type == MwCHART_3D_PIE) { + double sum = 0; + int radius = r.width < r.height ? r.width : r.height; + double cangle = 0; + int k; + double vsquish = type == MwCHART_3D_PIE ? 2 : 1; + MwPoint p[360 + 1 + 1]; for(i = 0; i < arrlen(c->entries); i++) { if(c->entries[i].value > 0) sum += c->entries[i].value; } - for(k = 0; k < 2; k++) { + for(k = 0; k < 4; k++) { for(i = 0; i < arrlen(c->entries); i++) { MwLLColor color; + MwLLColor colorl; double angle = c->entries[i].value / sum * 360; - MwPoint p[360 + 1 + 1]; - int div = angle / PIE_DIV; + int div = angle / PIE_DIV; int j; int count; if(c->entries[i].value <= 0) continue; + if((k == 0 || k == 1) && type == MwCHART_PIE) continue; - color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); p[0].x = r.width / 2; p[0].y = r.height / 2; @@ -269,31 +274,72 @@ static void draw(MwWidget handle) { double a = angle / div * j; p[div - j + 1].x = p[0].x + cos((cangle + a - 90) / 180 * M_PI) * radius / 2; - p[div - j + 1].y = p[0].y + sin((cangle + a - 90) / 180 * M_PI) * radius / 2; + p[div - j + 1].y = p[0].y + sin((cangle + a - 90) / 180 * M_PI) * radius / 2 / vsquish; } count = j + 1; - if(k == 0) { - MwLLPolygon(handle->lowlevel, p, count, color); - } else { + if((k == 0 || k == 1) && type == MwCHART_3D_PIE) { + int j; + MwPoint p2[360 + 1 + 1]; + int d = 0; + + for(d = 1; d <= 2; d++) { + for(j = 0; j < count - 1; j++) { + p2[3 + j] = p[1 + j]; + p2[3 + j].y += radius / 8 / d; + } + + p2[0] = p[count - 1]; + p2[1] = p[0]; + p2[2] = p[1]; + + if(k == 0) { + MwLLPolygon(handle->lowlevel, p2, count + 2, color); + } else if(d == 1 && k == 1) { + for(j = 3; j < count + 1; j++) { + if(!modern) MwLLLine(handle->lowlevel, &p2[j], border); + } + + p[0] = p[1]; + p[0].y += radius / 8; + if(!modern) MwLLLine(handle->lowlevel, p, border); + } + } + } + + if(k == 2) { + MwLLPolygon(handle->lowlevel, p, count, type == MwCHART_3D_PIE ? colorl : color); + } else if(k == 3) { int j; p[count] = p[0]; for(j = 0; j < count; j++) { - MwLLLine(handle->lowlevel, &p[j], border); + if(!modern) MwLLLine(handle->lowlevel, &p[j], border); } p[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; - p[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; + p[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4 / vsquish; MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); } cangle += angle; + MwLLFreeColor(colorl); MwLLFreeColor(color); } } + + if(!modern && type == MwCHART_3D_PIE) { + p[0].x = r.width / 2 - radius / 2; + p[0].y = r.height / 2; + p[1] = p[0]; + p[1].y += radius / 8; + MwLLLine(handle->lowlevel, p, border); + + p[0].x = p[1].x = r.width / 2 + radius / 2; + MwLLLine(handle->lowlevel, p, border); + } } MwLLFreeColor(border); From f0fc3fa174d8e2b61a7d96f74136402e3e06059f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 14 Sep 2026 07:09:43 +0900 Subject: [PATCH 078/168] wayland backend now doublebuffered! --- CMakeLists.txt | 1 - include/Mw/LowLevel/Cairo.h | 2 + include/Mw/LowLevel/Wayland.h | 17 ----- pl/rules.pl | 1 - src/backend/cairo.c | 55 +++++++------- src/backend/wayland/buffer.c | 33 --------- src/backend/wayland/interfaces.c | 1 - src/backend/wayland/wayland.c | 120 ++++++++++++++----------------- src/widget/opengl.c | 5 -- 9 files changed, 86 insertions(+), 149 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ec1ed8..534614f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,7 +261,6 @@ if(MW_USE_WAYLAND) scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1") - scan_wayland_protocol("staging" "fifo" "-v1") scan_wayland_protocol_from_file("wlr-layer-shell" "wlr-layer-shell-unstable-v1.xml") target_sources( diff --git a/include/Mw/LowLevel/Cairo.h b/include/Mw/LowLevel/Cairo.h index dd2cfa3..680c651 100644 --- a/include/Mw/LowLevel/Cairo.h +++ b/include/Mw/LowLevel/Cairo.h @@ -188,8 +188,10 @@ struct _MwLLCairo { struct _MwLLCommon common; cairo_surface_t* front_cs; + cairo_surface_t* front_cs_back; cairo_surface_t* back_cs; cairo_t* front_cairo; + cairo_t* front_cairo_back; cairo_t* back_cairo; /* The cairo to actually use for draw operations. Typically is front_cairo, but wayland's MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */ cairo_t* selected_cairo; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index b9cbf52..fd97178 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -207,7 +207,6 @@ MwInline int wayland_load_funcs() { #include "Wayland/relative-pointer-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h" #include "Wayland/wlr-layer-shell-client-protocol.h" -#include "Wayland/fifo-client-protocol.h" #endif typedef struct wayland_protocol { @@ -266,7 +265,6 @@ struct _MwLLWaylandShmBuffer { struct wl_buffer* shm_buffer_back; struct wl_surface* surface; struct wl_output* output; - struct wp_fifo_v1* fifo; MwU8* buf; MwU8* buf_back; @@ -436,8 +434,6 @@ struct _MwLLWayland { struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; struct _MwLLWaylandShmBuffer* icon; - MwBool fifo_wait; - MwBool disable_fifo; MwLLPixmap icon_pixmap; @@ -475,17 +471,6 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland); /* Destroy the backbuffer */ void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* handle); -/* Bind a wp_fifo_v1 object to `buffer`'s surface, if wp_fifo_manager_v1 is available and it doesn't have one already. */ -void MwLLWaylandFifoSurfaceSetup(struct _MwLLWayland* wayland, struct _MwLLWaylandShmBuffer* buffer); -/* Destroy `buffer`'s wp_fifo_v1 object, if any. */ -void MwLLWaylandFifoSurfaceDestroy(struct _MwLLWaylandShmBuffer* buffer); -/* Commit `buffer`'s surface, constraining the update to the next display refresh via wp_fifo_v1 if bound. */ -void MwLLWaylandFifoCommit(struct _MwLLWaylandShmBuffer* buffer); - -#ifdef MW_VULKAN -#warning Wayland backend currently disabled by default when Vulkan enabled. Use with caution (MW_BACKEND=wayland to override). -#endif - void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height); void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer); void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer); @@ -508,8 +493,6 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_ /* Flush Wayland events */ void MwLLWaylandFlush(MwLL handle); -void MwLLWaylandCascadeChildren(MwLL handle); - /* Standard procedure before event callbacks in Wayland */ #define WAYLAND_EVENT_OP_START(self) diff --git a/pl/rules.pl b/pl/rules.pl index 220e550..9d2081c 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -66,7 +66,6 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); - scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 65380fb..0b74b42 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -6,38 +6,38 @@ cairo_call_table_t cairo_call_tbl; void MwLLCairoPolygon(struct _MwLLCairo handle, MwPoint* points, int points_count, MwLLColor color) { int i; - cairo_set_source_rgba(handle.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); - cairo_new_path(handle.front_cairo); + cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); + cairo_new_path(handle.front_cairo_back); for(i = 0; i < points_count; i++) { if(i == 0) { - cairo_move_to(handle.front_cairo, points[i].x, points[i].y); + cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); } else { - cairo_line_to(handle.front_cairo, points[i].x, points[i].y); + cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); } } - cairo_close_path(handle.front_cairo); + cairo_close_path(handle.front_cairo_back); - cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_SOURCE); - cairo_fill(handle.front_cairo); - cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_OVER); + cairo_set_operator(handle.front_cairo_back, CAIRO_OPERATOR_SOURCE); + cairo_fill(handle.front_cairo_back); + cairo_set_operator(handle.front_cairo_back, CAIRO_OPERATOR_OVER); }; void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { int i; - cairo_set_antialias(handle.front_cairo, CAIRO_ANTIALIAS_NONE); - cairo_set_line_cap(handle.front_cairo, CAIRO_LINE_CAP_SQUARE); - cairo_set_source_rgba(handle.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); - cairo_new_path(handle.front_cairo); + cairo_set_antialias(handle.front_cairo_back, CAIRO_ANTIALIAS_NONE); + cairo_set_line_cap(handle.front_cairo_back, CAIRO_LINE_CAP_SQUARE); + cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); + cairo_new_path(handle.front_cairo_back); for(i = 0; i < 2; i++) { if(i == 0) { - cairo_move_to(handle.front_cairo, points[i].x, points[i].y); + cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); } else { - cairo_line_to(handle.front_cairo, points[i].x, points[i].y); + cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); } } - cairo_close_path(handle.front_cairo); - cairo_stroke(handle.front_cairo); + cairo_close_path(handle.front_cairo_back); + cairo_stroke(handle.front_cairo_back); }; MwLLPixmap MwLLCairoCreatePixmap(struct _MwLLCairo handle, unsigned char* data, int width, int height) { @@ -88,7 +88,7 @@ void MwLLCairoDestroyPixmap(MwLLPixmap pixmap) { void MwLLCairoDrawPixmap(struct _MwLLCairo handle, MwRect* rect, MwLLPixmap pixmap) { cairo_t* c; cairo_surface_t* cs; - cairo_t* selected_cairo = handle.selected_cairo ? handle.selected_cairo : handle.front_cairo; + cairo_t* selected_cairo = handle.selected_cairo ? handle.selected_cairo : handle.front_cairo_back; cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); c = cairo_create(cs); @@ -101,7 +101,7 @@ void MwLLCairoDrawPixmap(struct _MwLLCairo handle, MwRect* rect, MwLLPixmap pixm cairo_set_source_surface(c, pixmap->cairo.cs, 0, 0); cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); - cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_OVER); + cairo_set_operator(handle.front_cairo_back, CAIRO_OPERATOR_OVER); cairo_paint(c); @@ -118,7 +118,9 @@ void MwLLCairoFrontSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU3 } else { cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); } - cairo->front_cairo = cairo_create(cairo->front_cs); + cairo->front_cs_back = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo->front_cairo_back = cairo_create(cairo->front_cs_back); + cairo->front_cairo = cairo_create(cairo->front_cs); } void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) { @@ -132,6 +134,7 @@ void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) { cairo_destroy(cairo->front_cairo); + cairo_destroy(cairo->front_cairo_back); cairo_surface_destroy(cairo->front_cs); }; void MwLLCairoBackDestroy(struct _MwLLCairo* cairo) { @@ -169,7 +172,7 @@ static void MwLLDestroyImpl(MwLL handle) { } static void MwLLBeginDrawImpl(MwLL handle) { - handle->cairo.selected_cairo = handle->cairo.front_cairo; + handle->cairo.selected_cairo = handle->cairo.front_cairo_back; } static void MwLLEndDrawImpl(MwLL handle) { } @@ -212,8 +215,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -257,10 +260,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index 3ee5e3c..cb1eca5 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -2,39 +2,6 @@ #include #include "../../../external/stb_ds.h" -/* Bind a wp_fifo_v1 object to `buffer`'s surface, if wp_fifo_manager_v1 is available and it doesn't have one already. */ -void MwLLWaylandFifoSurfaceSetup(struct _MwLLWayland* wayland, struct _MwLLWaylandShmBuffer* buffer) { - wayland_protocol_t* fifo_manager; - - if(buffer->fifo || !buffer->surface) { - return; - } - - fifo_manager = shget(wayland->wl_protocol_map, wp_fifo_manager_v1_interface.name); - if(!fifo_manager) { - return; - } - - buffer->fifo = wp_fifo_manager_v1_get_fifo(fifo_manager->context, buffer->surface); -} - -/* Destroy `buffer`'s wp_fifo_v1 object, if any. */ -void MwLLWaylandFifoSurfaceDestroy(struct _MwLLWaylandShmBuffer* buffer) { - if(buffer->fifo) { - wp_fifo_v1_destroy(buffer->fifo); - buffer->fifo = NULL; - } -} - -/* Commit `buffer`'s surface, constraining the update to the next display refresh via wp_fifo_v1 if bound. */ -void MwLLWaylandFifoCommit(struct _MwLLWaylandShmBuffer* buffer) { - if(buffer->fifo) { - wp_fifo_v1_set_barrier(buffer->fifo); - wp_fifo_v1_wait_barrier(buffer->fifo); - } - wl_surface_commit(buffer->surface); -} - void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 247919c..cbab2ad 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -600,7 +600,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time MwLLDispatch(currentlyHeldWidgets[i], move, &p); } - MwLLWaylandCascadeChildren(self); } if(self->wayland.backbuffer.surface) { wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 7253c00..6154664 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -225,11 +225,8 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { // Yes this is needed every time, it's how we fix weston. if(self->wayland.configured) wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - if(self->wayland.fifo_wait) { - MwLLWaylandFifoCommit(buffer); - } else { - wl_surface_commit(buffer->surface); - } + + wl_surface_commit(buffer->surface); } } } @@ -278,9 +275,7 @@ static void setup_toplevel(MwLL r, int x, int y) { /* Create a wl_surface, a xdg_surface and a xdg_toplevel */ r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); r->wayland.backbuffer.surface = wl_compositor_create_surface(r->wayland.compositor); - MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); - MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.backbuffer); - r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); + r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); wl_subsurface_set_desync(r->wayland.toplevel->ssurface); r->wayland.toplevel->xdg_surface = @@ -356,8 +351,6 @@ static void destroy_toplevel(MwLL r) { * after this function returns, so every widget type that binds a seat (toplevel, popup, * layer surface) releases them the same way instead of leaking or double-freeing them. */ - MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); - MwLLWaylandFifoSurfaceDestroy(&r->wayland.backbuffer); wl_surface_destroy(r->wayland.framebuffer.surface); free(r->wayland.toplevel); @@ -521,7 +514,6 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { r->wayland.xkb_state = topmost_parent->wayland.xkb_state; r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); - MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); r->wayland.popup->xdg_surface = xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface); @@ -563,8 +555,6 @@ static void destroy_popup(MwLL r) { xdg_positioner_destroy(r->wayland.popup->xdg_positioner); - MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); - wl_surface_destroy(r->wayland.framebuffer.surface); wl_registry_destroy(r->wayland.registry); @@ -648,7 +638,6 @@ static void setup_layer_surface(MwLL r, int x, int y, int width, int height) { r->wayland.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); - MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); r->wayland.layer_surface->surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, r->wayland.framebuffer.surface, NULL, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "milsko-surfaces"); @@ -679,8 +668,6 @@ static void destroy_layer_surface(MwLL r) { zxdg_decoration_manager_v1_destroy(dec->manager); } - MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); - wl_surface_destroy(r->wayland.framebuffer.surface); wl_compositor_destroy(r->wayland.compositor); @@ -810,15 +797,15 @@ static void clip(MwLL handle) { handle->wayland.clipping_rect.height = my - cy; MwLLWaylandRegionSetup(handle); - cairo_reset_clip(handle->wayland.cairo.front_cairo); + cairo_reset_clip(handle->wayland.cairo.front_cairo_back); if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL && !handle->wayland.is_toplevel) { - cairo_rectangle(handle->wayland.cairo.front_cairo, cx - x, cy - y, mx - cx, my - cy); - cairo_clip(handle->wayland.cairo.front_cairo); + cairo_rectangle(handle->wayland.cairo.front_cairo_back, cx - x, cy - y, mx - cx, my - cy); + cairo_clip(handle->wayland.cairo.front_cairo_back); } if(handle->wayland.is_clipping) { - cairo_rectangle(handle->wayland.cairo.front_cairo, handle->wayland.clip.x, handle->wayland.clip.y, handle->wayland.clip.width, handle->wayland.clip.height); - cairo_clip(handle->wayland.cairo.front_cairo); + cairo_rectangle(handle->wayland.cairo.front_cairo_back, handle->wayland.clip.x, handle->wayland.clip.y, handle->wayland.clip.width, handle->wayland.clip.height); + cairo_clip(handle->wayland.cairo.front_cairo_back); } } } @@ -933,22 +920,31 @@ static void draw_children(MwLL handle); static void draw_child(MwLL handle, MwLL child) { cairo_t* c; cairo_surface_t* cs; - cairo_t* selected_cairo = handle->wayland.cairo.front_cairo; + cairo_t* selected_cairo; + MwLL topmost_parent = handle; + + if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP) { + while(topmost_parent->wayland.parent) { + topmost_parent = topmost_parent->wayland.parent; + } + } wl_surface_commit(child->wayland.framebuffer.surface); cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, child->wayland.ww, child->wayland.wh); c = cairo_create(cs); - cairo_set_source_surface(c, child->wayland.cairo.front_cs, 0, 0); + cairo_set_source_surface(c, child->wayland.cairo.front_cs_back, 0, 0); cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); - cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_OVER); + cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_OVER); cairo_paint(c); - cairo_set_source_surface(selected_cairo, cs, child->wayland.x, child->wayland.y); - cairo_paint(selected_cairo); + // printf("%d %d\n", child->wayland.x, child->wayland.y); + + cairo_set_source_surface(handle->wayland.cairo.front_cairo_back, cs, child->wayland.x, child->wayland.y); + cairo_paint(handle->wayland.cairo.front_cairo_back); cairo_destroy(c); cairo_surface_destroy(cs); @@ -965,20 +961,25 @@ static void draw_children(MwLL handle) { handle->wayland.events_pending = MwFALSE; } -static void cascade_child(MwLL handle, MwLL child) { - child->wayland.do_cascading_draw = 10; -} +static void frontbuffer_draw(MwLL handle) { + cairo_t* c; + cairo_surface_t* cs; -static void count_child(MwLL handle, MwLL child) { - handle->wayland.cascading_child_num++; -} + cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, handle->wayland.ww, handle->wayland.wh); + c = cairo_create(cs); -void MwLLWaylandCascadeChildren(MwLL handle) { - handle->wayland.cascading_child_num = 0; - MwLLWaylandChildrenIterate(handle, count_child); + cairo_set_source_surface(c, handle->wayland.cairo.front_cs_back, 0, 0); + cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); - handle->wayland.do_cascading_draw = handle->wayland.cascading_child_num * 10; - MwLLWaylandChildrenIterate(handle, cascade_child); + cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_OVER); + + cairo_paint(c); + + cairo_set_source_surface(handle->wayland.cairo.front_cairo, cs, 0, 0); + cairo_paint(handle->wayland.cairo.front_cairo); + + cairo_destroy(c); + cairo_surface_destroy(cs); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -1069,7 +1070,6 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - MwLLWaylandRegionInvalidate(handle); if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) { @@ -1082,8 +1082,11 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { /* toplevels cannot be moved */ break; case MwLL_WAYLAND_SUBLEVEL: - /* sublevels are drawn according to their own x/y */ + { + if(handle->wayland.parent) + MwLLForceRender(handle->wayland.parent); break; + } case MwLL_WAYLAND_POPUP: xdg_positioner_set_anchor_rect(handle->wayland.popup->xdg_positioner, handle->wayland.parent->wayland.x, handle->wayland.parent->wayland.y, handle->wayland.ww, handle->wayland.wh); xdg_positioner_set_offset(handle->wayland.popup->xdg_positioner, x, y); @@ -1171,16 +1174,15 @@ const float_color one = {.2627451, .37254902, .49411765}; const float_color two = {.05490196, .17254902, .30588235}; static void MwLLBeginDrawImpl(MwLL handle) { - - cairo_save(handle->wayland.cairo.front_cairo); - cairo_set_source_rgba(handle->wayland.cairo.front_cairo, 0, 0, 0, 0); - cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_SOURCE); - cairo_rectangle(handle->wayland.cairo.front_cairo, 0, 0, handle->wayland.ww, handle->wayland.wh); - cairo_fill(handle->wayland.cairo.front_cairo); - cairo_restore(handle->wayland.cairo.front_cairo); + cairo_save(handle->wayland.cairo.front_cairo_back); + cairo_set_source_rgba(handle->wayland.cairo.front_cairo_back, 0, 0, 0, 0); + cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_SOURCE); + cairo_rectangle(handle->wayland.cairo.front_cairo_back, 0, 0, handle->wayland.ww, handle->wayland.wh); + cairo_fill(handle->wayland.cairo.front_cairo_back); + cairo_restore(handle->wayland.cairo.front_cairo_back); if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) { - handle->wayland.cairo.selected_cairo = handle->wayland.cairo.front_cairo; + handle->wayland.cairo.selected_cairo = handle->wayland.cairo.front_cairo_back; return; } @@ -1310,7 +1312,7 @@ static void MwLLBeginDrawImpl(MwLL handle) { } MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } - handle->wayland.cairo.selected_cairo = handle->wayland.cairo.front_cairo; + handle->wayland.cairo.selected_cairo = handle->wayland.cairo.front_cairo_back; } static void MwLLEndDrawImpl(MwLL handle) { @@ -1320,7 +1322,9 @@ static void MwLLEndDrawImpl(MwLL handle) { } MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); - MwLLWaylandCascadeChildren(handle); + if(handle->wayland.type != MwLL_WAYLAND_SUBLEVEL) { + handle->wayland.do_cascading_draw = 1; + } } } @@ -1385,8 +1389,7 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->wayland.do_cascading_draw) { draw_children(handle); - if(handle->wayland.do_cascading_draw > 0) - handle->wayland.do_cascading_draw--; + frontbuffer_draw(handle); } handle->wayland.end_time = MwTimeGetTick(); @@ -1437,12 +1440,10 @@ static int MwLLPendingImpl(MwLL handle) { return pending; } - if(!handle->wayland.disable_fifo) handle->wayland.fifo_wait = MwTRUE; MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } - if(!handle->wayland.disable_fifo) handle->wayland.fifo_wait = MwFALSE; return handle->wayland.force_render || handle->wayland.events_pending || pending; } @@ -1458,11 +1459,9 @@ static void MwLLNextEventImpl(MwLL handle) { } if(handle->wayland.force_render) { - handle->wayland.fifo_wait = MwTRUE; MwLLDispatch(handle, draw, NULL); if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); handle->wayland.force_render = 0; - handle->wayland.fifo_wait = MwFALSE; } if(handle->wayland.events_pending) { handle->wayland.events_pending = 0; @@ -1559,7 +1558,6 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { } static void MwLLForceRenderImpl(MwLL handle) { - if(!handle->wayland.configured) { return; } @@ -1567,9 +1565,6 @@ static void MwLLForceRenderImpl(MwLL handle) { wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); handle->wayland.force_render = MwTRUE; - if(handle->wayland.parent) { - handle->wayland.parent->wayland.force_render = MwTRUE; - } } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { @@ -1919,14 +1914,9 @@ static int MwLLWaylandCallInitImpl(void) { } else { loadWayland |= (strcmp(mw_backend_env, "wayland") == 0); } - } - - /* NOTE: when vulkan is enabled, refuse to default to wayland. Remove this if I ever get Vulkan widget working with the new surfaces system. */ -#ifndef MW_VULKAN - else if(getenv("WAYLAND_DISPLAY")) { + } else if(getenv("WAYLAND_DISPLAY")) { loadWayland |= (getenv("WAYLAND_DISPLAY") != NULL); } -#endif #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 9e1b91e..c9bb3f4 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -240,11 +240,6 @@ static int wcreate(MwWidget handle) { waylandopengl_t* o = r = malloc(sizeof(*o)); int gbm_format = 0; EGLConfig egl_configs[1024]; - MwWidget topmost_parent = handle; - - /* Disable fifo waiting when we have an OpenGL widget */ - while(topmost_parent->parent) topmost_parent = topmost_parent->parent; - topmost_parent->lowlevel->wayland.disable_fifo = MwTRUE; memset(o, 0, sizeof(waylandopengl_t)); From 66ea53f5231baa8230c98c155505ea05fa27807a Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 07:15:12 +0900 Subject: [PATCH 079/168] fix --- src/backend/cairo.c | 1 + src/backend/wayland/wayland.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 0b74b42..7f421ac 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -27,6 +27,7 @@ void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { cairo_set_antialias(handle.front_cairo_back, CAIRO_ANTIALIAS_NONE); cairo_set_line_cap(handle.front_cairo_back, CAIRO_LINE_CAP_SQUARE); + cairo_set_line_width(handle.front_cairo_back, 1); cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); cairo_new_path(handle.front_cairo_back); for(i = 0; i < 2; i++) { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 6154664..0c771ab 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1920,7 +1920,7 @@ static int MwLLWaylandCallInitImpl(void) { #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { - loadWayland = 0; + //loadWayland = 0; } #endif From bf803f0ad5b08a5cfdf44ece752de62b4adc1adb Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 07:20:17 +0900 Subject: [PATCH 080/168] ok --- src/backend/cairo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 7f421ac..38345eb 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -34,7 +34,7 @@ void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { if(i == 0) { cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); } else { - cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); + cairo_line_to(handle.front_cairo_back, points[i].x + 1, points[i].y + 1); } } cairo_close_path(handle.front_cairo_back); From 98536a07db9fefa608a239b7ab5d976122a43feb Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 07:21:14 +0900 Subject: [PATCH 081/168] fix --- src/widget/chart.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widget/chart.c b/src/widget/chart.c index 9c87e3f..eaaea55 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -320,6 +320,9 @@ static void draw(MwWidget handle) { p[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; p[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4 / vsquish; + + handle->bgcolor = type == MwCHART_3D_PIE ? colorl : color; + MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); } From e73734c97bb756cd78912b86f51740da329d0bb6 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 07:21:37 +0900 Subject: [PATCH 082/168] revive wsl hack --- src/backend/wayland/wayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 0c771ab..6154664 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1920,7 +1920,7 @@ static int MwLLWaylandCallInitImpl(void) { #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { - //loadWayland = 0; + loadWayland = 0; } #endif From 02347fb70549f1a23e8079547c65da934e58f4e7 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 07:27:35 +0900 Subject: [PATCH 085/168] fix --- src/backend/cairo.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 38345eb..62fa6ba 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -29,15 +29,13 @@ void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { cairo_set_line_cap(handle.front_cairo_back, CAIRO_LINE_CAP_SQUARE); cairo_set_line_width(handle.front_cairo_back, 1); cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); - cairo_new_path(handle.front_cairo_back); for(i = 0; i < 2; i++) { if(i == 0) { cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); } else { - cairo_line_to(handle.front_cairo_back, points[i].x + 1, points[i].y + 1); + cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); } } - cairo_close_path(handle.front_cairo_back); cairo_stroke(handle.front_cairo_back); }; From b54721a323ebe1a7fbb01522c2a846bf26c99c42 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 07:58:11 +0900 Subject: [PATCH 086/168] wip line chart --- examples/basic/periodic.c | 14 ++++- include/Mw/Constants.h | 3 +- src/backend/cairo.c | 12 ++-- src/widget/chart.c | 129 +++++++++++++++++++++++++++----------- 4 files changed, 112 insertions(+), 46 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index adaf35b..f7148da 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -294,6 +294,19 @@ int main() { MwChartAdd(w, -1, "G", 10, NULL); MwChartAdd(w, -1, "H", 20, NULL); + f = frame("Line Chart", -PaddingContent, -PaddingContent, MwChartClass, + MwNtype, MwCHART_LINE, + NULL); + w = child(f); + MwChartAdd(w, -1, "A", -800, NULL); + MwChartAdd(w, -1, "B", -400, NULL); + MwChartAdd(w, -1, "C", -200, NULL); + MwChartAdd(w, -1, "D", -100, NULL); + MwChartAdd(w, -1, "E", 100, NULL); + MwChartAdd(w, -1, "F", 200, NULL); + MwChartAdd(w, -1, "G", 400, NULL); + MwChartAdd(w, -1, "H", 800, NULL); + f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL); w = child(f); MwComboBoxAdd(w, -1, "Hello!"); @@ -306,7 +319,6 @@ int main() { f = frame("Label", -PaddingContent, -PaddingContent, MwLabelClass, MwNtext, "Epic text\nNewline can be used too!", - MwNcolumnSpan, 2, NULL); f = frame("ListBox", -PaddingContent, -PaddingContent, MwListBoxClass, diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index 6379fef..acd6b05 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -117,7 +117,8 @@ enum MwCHART { MwCHART_BAR = 0, MwCHART_3D_BAR, MwCHART_PIE, - MwCHART_3D_PIE + MwCHART_3D_PIE, + MwCHART_LINE }; enum MwMOUSE { diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 62fa6ba..3683ca8 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -214,8 +214,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -259,10 +259,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/widget/chart.c b/src/widget/chart.c index eaaea55..d66cc61 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -62,6 +62,19 @@ static void draw_line(MwWidget handle, const char* text, double x, double y, dou MwLLLine(handle->lowlevel, &p[0], color); } +#define CALC_VMIN_VMAX \ + if(vmin > 0) { \ + vmin = 0; \ + } else if(vmin < 0) { \ + vmin -= (double)width / r.height * (vmax - vmin); \ + } \ +\ + if(vmax < 0) { \ + vmax = 0; \ + } else if(vmax > 0) { \ + vmax += (double)width / r.height * (vmax - vmin); \ + } + static void draw(MwWidget handle) { int ColorDiff = MwGetColorDifference(handle); MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); @@ -73,13 +86,14 @@ static void draw(MwWidget handle) { int n; int gap; int width; - MwRect node; double vmin = 0xffffffff; double vmax = -0xffffffff; int space = MwTextHeight(handle, NULL, "M"); MwPoint p[2]; int type = MwGetInteger(handle, MwNtype); int modern = MwGetInteger(handle, MwNmodernLook); + double ovmin; + double ovmax; for(n = 0; colors[n] != NULL; n++); @@ -91,6 +105,9 @@ static void draw(MwWidget handle) { if(MwGetInteger(handle, MwNminValue) != MwDEFAULT) vmin = MwGetInteger(handle, MwNminValue); if(MwGetInteger(handle, MwNmaxValue) != MwDEFAULT) vmax = MwGetInteger(handle, MwNmaxValue); + ovmin = vmin; + ovmax = vmax; + r.x = 0; r.y = 0; r.width = MwGetInteger(handle, MwNwidth); @@ -98,11 +115,10 @@ static void draw(MwWidget handle) { MwDrawRect(handle, &r, base); if(type == MwCHART_BAR || type == MwCHART_3D_BAR) { - double s = 1.5; - double ovmin = vmin; - double ovmax = vmax; + double s = 1.5; double twidth; char buf[128]; + MwRect node; node.x = 0; @@ -121,20 +137,10 @@ static void draw(MwWidget handle) { width = (r.width - node.x) * s / (arrlen(c->entries) * (1 + s) + 1); gap = width / s; + CALC_VMIN_VMAX; + twidth = (width + gap) * arrlen(c->entries) + gap; - if(vmin > 0) { - vmin = 0; - } else if(vmin < 0) { - vmin -= (double)width / r.height * (vmax - vmin); - } - - if(vmax < 0) { - vmax = 0; - } else if(vmax > 0) { - vmax += (double)width / r.height * (vmax - vmin); - } - sprintf(buf, NUMFMT, ovmax); draw_line(handle, buf, node.x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); @@ -247,7 +253,7 @@ static void draw(MwWidget handle) { double cangle = 0; int k; double vsquish = type == MwCHART_3D_PIE ? 2 : 1; - MwPoint p[360 + 1 + 1]; + MwPoint p2[360 + 1 + 1]; for(i = 0; i < arrlen(c->entries); i++) { if(c->entries[i].value > 0) sum += c->entries[i].value; @@ -268,62 +274,62 @@ static void draw(MwWidget handle) { color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); - p[0].x = r.width / 2; - p[0].y = r.height / 2; + p2[0].x = r.width / 2; + p2[0].y = r.height / 2; for(j = 0; j <= div; j++) { double a = angle / div * j; - p[div - j + 1].x = p[0].x + cos((cangle + a - 90) / 180 * M_PI) * radius / 2; - p[div - j + 1].y = p[0].y + sin((cangle + a - 90) / 180 * M_PI) * radius / 2 / vsquish; + p2[div - j + 1].x = p2[0].x + cos((cangle + a - 90) / 180 * M_PI) * radius / 2; + p2[div - j + 1].y = p2[0].y + sin((cangle + a - 90) / 180 * M_PI) * radius / 2 / vsquish; } count = j + 1; if((k == 0 || k == 1) && type == MwCHART_3D_PIE) { int j; - MwPoint p2[360 + 1 + 1]; + MwPoint p3[360 + 1 + 1]; int d = 0; for(d = 1; d <= 2; d++) { for(j = 0; j < count - 1; j++) { - p2[3 + j] = p[1 + j]; - p2[3 + j].y += radius / 8 / d; + p3[3 + j] = p2[1 + j]; + p3[3 + j].y += radius / 8 / d; } - p2[0] = p[count - 1]; - p2[1] = p[0]; - p2[2] = p[1]; + p3[0] = p2[count - 1]; + p3[1] = p2[0]; + p3[2] = p2[1]; if(k == 0) { - MwLLPolygon(handle->lowlevel, p2, count + 2, color); + MwLLPolygon(handle->lowlevel, p3, count + 2, color); } else if(d == 1 && k == 1) { for(j = 3; j < count + 1; j++) { - if(!modern) MwLLLine(handle->lowlevel, &p2[j], border); + if(!modern) MwLLLine(handle->lowlevel, &p3[j], border); } - p[0] = p[1]; - p[0].y += radius / 8; - if(!modern) MwLLLine(handle->lowlevel, p, border); + p2[0] = p2[1]; + p2[0].y += radius / 8; + if(!modern) MwLLLine(handle->lowlevel, p2, border); } } } if(k == 2) { - MwLLPolygon(handle->lowlevel, p, count, type == MwCHART_3D_PIE ? colorl : color); + MwLLPolygon(handle->lowlevel, p2, count, type == MwCHART_3D_PIE ? colorl : color); } else if(k == 3) { int j; - p[count] = p[0]; + p[count] = p2[0]; for(j = 0; j < count; j++) { - if(!modern) MwLLLine(handle->lowlevel, &p[j], border); + if(!modern) MwLLLine(handle->lowlevel, &p2[j], border); } - p[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; - p[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4 / vsquish; + p2[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; + p2[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4 / vsquish; handle->bgcolor = type == MwCHART_3D_PIE ? colorl : color; - MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); + MwDrawText(handle, NULL, p2, c->entries[i].name, MwALIGNMENT_CENTER, border); } cangle += angle; @@ -341,6 +347,53 @@ static void draw(MwWidget handle) { MwLLLine(handle->lowlevel, p, border); p[0].x = p[1].x = r.width / 2 + radius / 2; + MwLLLine(handle->lowlevel, p, border); + } + } else if(type == MwCHART_LINE) { + char buf[128]; + MwRect node; + double twidth; + double x = 0; + + for(i = 0; i < arrlen(c->entries); i++) { + int w; + + sprintf(buf, NUMFMT, c->entries[i].value); + + w = MwTextWidth(handle, NULL, buf); + + if(x < w) x = w; + } + + width = 16; + twidth = r.width - x; + + CALC_VMIN_VMAX; + + sprintf(buf, NUMFMT, ovmax); + draw_line(handle, buf, x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + draw_line(handle, "0", x, (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + sprintf(buf, NUMFMT, ovmin); + draw_line(handle, buf, x, (r.height - space) - (ovmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + draw_line(handle, "", x, (r.height - space) - (vmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + p[0].x = x; + p[0].y = 0; + + p[1] = p[0]; + p[1].y = r.height - space; + + MwLLLine(handle->lowlevel, p, border); + + for(i = 1; i < arrlen(c->entries); i++) { + p[0].x = x + (r.width - x) / (arrlen(c->entries) + 1) * i; + p[0].y = (r.height - space) - (c->entries[i - 1].value - vmin) / (vmax - vmin) * (r.height - space); + p[1].x = x + (r.width - x) / (arrlen(c->entries) + 1) * (i + 1); + p[1].y = (r.height - space) - (c->entries[i].value - vmin) / (vmax - vmin) * (r.height - space); + MwLLLine(handle->lowlevel, p, border); } } From ef7d7451341727ea8db240d8079e8d139e4c2c2e Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 14 Sep 2026 08:59:55 +0900 Subject: [PATCH 087/168] safety and separation --- src/widget/chart.c | 629 ++++++++++++++++++++++++--------------------- 1 file changed, 334 insertions(+), 295 deletions(-) diff --git a/src/widget/chart.c b/src/widget/chart.c index d66cc61..67753c9 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -75,25 +75,337 @@ static void draw_line(MwWidget handle, const char* text, double x, double y, dou vmax += (double)width / r.height * (vmax - vmin); \ } +static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int space, const char** colors, int n, MwLLColor border) { + int ColorDiff = MwGetColorDifference(handle); + MwChart c = handle->internal; + double s = 1.5; + double twidth; + char buf[128]; + MwRect node; + MwPoint p[2]; + int i; + int width; + int gap; + MwRect r = *_r; + double ovmin = vmin; + double ovmax = vmax; + int type = MwGetInteger(handle, MwNtype); + int modern = MwGetInteger(handle, MwNmodernLook); + + node.x = 0; + + for(i = 0; i < arrlen(c->entries); i++) { + int w; + + MwStringPrintIntoBuffer(buf, sizeof(buf), NUMFMT, c->entries[i].value); + + w = MwTextWidth(handle, NULL, buf); + + if(node.x < w) node.x = w; + } + + node.y = 0; + + width = (r.width - node.x) * s / (arrlen(c->entries) * (1 + s) + 1); + gap = width / s; + + CALC_VMIN_VMAX; + + twidth = (width + gap) * arrlen(c->entries) + gap; + + MwStringPrintIntoBuffer(buf, sizeof(buf), NUMFMT, ovmax); + draw_line(handle, buf, node.x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + draw_line(handle, "0", node.x, (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + MwStringPrintIntoBuffer(buf, sizeof(buf), NUMFMT, ovmin); + draw_line(handle, buf, node.x, (r.height - space) - (ovmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + p[0].x = node.x; + p[0].y = 0; + + p[1].x = node.x; + p[1].y = r.height - space; + MwLLLine(handle->lowlevel, &p[0], border); + + p[0].x = node.x; + p[0].y = r.height - space; + + p[1].x = node.x + twidth; + p[1].y = p[0].y; + MwLLLine(handle->lowlevel, &p[0], border); + + node.width = width; + for(i = 0; i < arrlen(c->entries); i++) { + MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + MwLLColor colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); + MwLLColor colord = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); + MwPoint persp_top[5]; + MwPoint persp_right[5]; + + node.x += gap; + + node.height = -c->entries[i].value / (vmax - vmin) * (r.height - space); + node.y = (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space); + + MwDrawRect(handle, &node, color); + + if(type == MwCHART_3D_BAR) { + MwRect node2 = node; + + MwFixRect(&node2); + + persp_top[0] = *(MwPoint*)&node2; + persp_top[1] = *(MwPoint*)&node2; + persp_top[1].x += node2.width; + + persp_top[2] = persp_top[1]; + persp_top[3] = persp_top[0]; + + persp_top[2].x += node2.width / 2; + persp_top[2].y -= node2.width / 2; + + persp_top[3].x += node2.width / 2; + persp_top[3].y -= node2.width / 2; + + persp_top[4] = persp_top[0]; + + MwLLPolygon(handle->lowlevel, persp_top, 4, colorl); + + persp_right[0] = *(MwPoint*)&node2; + persp_right[1] = *(MwPoint*)&node2; + persp_right[0].x += node2.width; + persp_right[1].x += node2.width; + persp_right[1].y += node2.height; + + persp_right[2] = persp_right[1]; + persp_right[3] = persp_right[0]; + + persp_right[2].x += node2.width / 2; + persp_right[2].y -= node2.width / 2; + + persp_right[3].x += node2.width / 2; + persp_right[3].y -= node2.width / 2; + + persp_right[4] = persp_right[0]; + + MwLLPolygon(handle->lowlevel, persp_right, 4, colord); + } + + if(!modern) { + MwDrawRectLine(handle, &node, border); + + if(type == MwCHART_3D_BAR) { + MwLLLine(handle->lowlevel, &persp_top[0], border); + MwLLLine(handle->lowlevel, &persp_top[1], border); + MwLLLine(handle->lowlevel, &persp_top[2], border); + MwLLLine(handle->lowlevel, &persp_top[3], border); + + MwLLLine(handle->lowlevel, &persp_right[0], border); + MwLLLine(handle->lowlevel, &persp_right[1], border); + MwLLLine(handle->lowlevel, &persp_right[2], border); + MwLLLine(handle->lowlevel, &persp_right[3], border); + } + } + + p[0].x = node.x + node.width / 2; + p[0].y = r.height - space / 2; + + MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); + + node.x += node.width; + + MwLLFreeColor(colord); + MwLLFreeColor(colorl); + MwLLFreeColor(color); + } +} + +static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, MwLLColor border) { + int ColorDiff = MwGetColorDifference(handle); + MwChart c = handle->internal; + double sum = 0; + MwRect r = *_r; + int radius = r.width < r.height ? r.width : r.height; + double cangle = 0; + int k; + int type = MwGetInteger(handle, MwNtype); + int modern = MwGetInteger(handle, MwNmodernLook); + double vsquish = type == MwCHART_3D_PIE ? 2 : 1; + int i; + MwPoint p[2]; + MwPoint p2[360 + 1 + 1]; + + for(i = 0; i < arrlen(c->entries); i++) { + if(c->entries[i].value > 0) sum += c->entries[i].value; + } + + for(k = 0; k < 4; k++) { + for(i = 0; i < arrlen(c->entries); i++) { + MwLLColor color; + MwLLColor colorl; + double angle = c->entries[i].value / sum * 360; + int div = angle / PIE_DIV; + int j; + int count; + + if(c->entries[i].value <= 0) continue; + if((k == 0 || k == 1) && type == MwCHART_PIE) continue; + + color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); + colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); + + p2[0].x = r.width / 2; + p2[0].y = r.height / 2; + for(j = 0; j <= div; j++) { + double a = angle / div * j; + + p2[div - j + 1].x = p2[0].x + cos((cangle + a - 90) / 180 * M_PI) * radius / 2; + p2[div - j + 1].y = p2[0].y + sin((cangle + a - 90) / 180 * M_PI) * radius / 2 / vsquish; + } + + count = j + 1; + + if((k == 0 || k == 1) && type == MwCHART_3D_PIE) { + int j; + MwPoint p3[360 + 1 + 1]; + int d = 0; + + for(d = 1; d <= 2; d++) { + for(j = 0; j < count - 1; j++) { + p3[3 + j] = p2[1 + j]; + p3[3 + j].y += radius / 8 / d; + } + + p3[0] = p2[count - 1]; + p3[1] = p2[0]; + p3[2] = p2[1]; + + if(k == 0) { + MwLLPolygon(handle->lowlevel, p3, count + 2, color); + } else if(d == 1 && k == 1) { + for(j = 3; j < count + 1; j++) { + if(!modern) MwLLLine(handle->lowlevel, &p3[j], border); + } + + p2[0] = p2[1]; + p2[0].y += radius / 8; + if(!modern) MwLLLine(handle->lowlevel, p2, border); + } + } + } + + if(k == 2) { + MwLLPolygon(handle->lowlevel, p2, count, type == MwCHART_3D_PIE ? colorl : color); + } else if(k == 3) { + int j; + + p2[count] = p2[0]; + for(j = 0; j < count; j++) { + if(!modern) MwLLLine(handle->lowlevel, &p2[j], border); + } + + p2[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; + p2[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4 / vsquish; + + handle->bgcolor = type == MwCHART_3D_PIE ? colorl : color; + + MwDrawText(handle, NULL, p2, c->entries[i].name, MwALIGNMENT_CENTER, border); + } + + cangle += angle; + + MwLLFreeColor(colorl); + MwLLFreeColor(color); + } + } + + if(!modern && type == MwCHART_3D_PIE) { + p[0].x = r.width / 2 - radius / 2; + p[0].y = r.height / 2; + p[1] = p[0]; + p[1].y += radius / 8; + MwLLLine(handle->lowlevel, p, border); + + p[0].x = p[1].x = r.width / 2 + radius / 2; + MwLLLine(handle->lowlevel, p, border); + } +} + +static void line_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int space, MwLLColor border) { + MwChart c = handle->internal; + char buf[128]; + double twidth; + double x = 0; + int j; + MwPoint p[2]; + MwRect r = *_r; + double ovmin = vmin; + double ovmax = vmax; + int i; + int width; + + for(i = 0; i < arrlen(c->entries); i++) { + int w; + + MwStringPrintIntoBuffer(buf, sizeof(buf), NUMFMT, c->entries[i].value); + + w = MwTextWidth(handle, NULL, buf); + + if(x < w) x = w; + } + + width = 16; + twidth = r.width - x; + + CALC_VMIN_VMAX; + + MwStringPrintIntoBuffer(buf, sizeof(buf), NUMFMT, ovmax); + draw_line(handle, buf, x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + draw_line(handle, "0", x, (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + MwStringPrintIntoBuffer(buf, sizeof(buf), NUMFMT, ovmin); + draw_line(handle, buf, x, (r.height - space) - (ovmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + draw_line(handle, "", x, (r.height - space) - (vmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); + + p[0].x = x; + p[0].y = 0; + + p[1] = p[0]; + p[1].y = r.height - space; + + MwLLLine(handle->lowlevel, p, border); + + for(j = 0; j < 2; j++) { + for(i = j == 0 ? 1 : 0; i < arrlen(c->entries); i++) { + p[0].x = x + (r.width - x) / (arrlen(c->entries) + 1) * i; + p[0].y = (r.height - space) - (c->entries[i - 1].value - vmin) / (vmax - vmin) * (r.height - space); + p[1].x = x + (r.width - x) / (arrlen(c->entries) + 1) * (i + 1); + p[1].y = (r.height - space) - (c->entries[i].value - vmin) / (vmax - vmin) * (r.height - space); + + if(j == 0) { + MwLLLine(handle->lowlevel, p, border); + } else { + MwDrawText(handle, NULL, &p[1], c->entries[i].name, MwALIGNMENT_CENTER, border); + } + } + } +} + static void draw(MwWidget handle) { - int ColorDiff = MwGetColorDifference(handle); - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNforeground)); MwRect r; MwChart c = handle->internal; int i; const char** colors = palette0; int n; - int gap; - int width; double vmin = 0xffffffff; double vmax = -0xffffffff; int space = MwTextHeight(handle, NULL, "M"); - MwPoint p[2]; - int type = MwGetInteger(handle, MwNtype); - int modern = MwGetInteger(handle, MwNmodernLook); - double ovmin; - double ovmax; + int type = MwGetInteger(handle, MwNtype); for(n = 0; colors[n] != NULL; n++); @@ -105,297 +417,24 @@ static void draw(MwWidget handle) { if(MwGetInteger(handle, MwNminValue) != MwDEFAULT) vmin = MwGetInteger(handle, MwNminValue); if(MwGetInteger(handle, MwNmaxValue) != MwDEFAULT) vmax = MwGetInteger(handle, MwNmaxValue); - ovmin = vmin; - ovmax = vmax; - r.x = 0; r.y = 0; r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); MwDrawRect(handle, &r, base); - if(type == MwCHART_BAR || type == MwCHART_3D_BAR) { - double s = 1.5; - double twidth; - char buf[128]; - MwRect node; - - node.x = 0; - - for(i = 0; i < arrlen(c->entries); i++) { - int w; - - sprintf(buf, NUMFMT, c->entries[i].value); - - w = MwTextWidth(handle, NULL, buf); - - if(node.x < w) node.x = w; - } - - node.y = 0; - - width = (r.width - node.x) * s / (arrlen(c->entries) * (1 + s) + 1); - gap = width / s; - - CALC_VMIN_VMAX; - - twidth = (width + gap) * arrlen(c->entries) + gap; - - sprintf(buf, NUMFMT, ovmax); - draw_line(handle, buf, node.x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - - draw_line(handle, "0", node.x, (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - - sprintf(buf, NUMFMT, ovmin); - draw_line(handle, buf, node.x, (r.height - space) - (ovmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - - p[0].x = node.x; - p[0].y = 0; - - p[1].x = node.x; - p[1].y = r.height - space; - MwLLLine(handle->lowlevel, &p[0], border); - - p[0].x = node.x; - p[0].y = r.height - space; - - p[1].x = node.x + twidth; - p[1].y = p[0].y; - MwLLLine(handle->lowlevel, &p[0], border); - - node.width = width; - for(i = 0; i < arrlen(c->entries); i++) { - MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); - MwLLColor colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); - MwLLColor colord = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); - MwPoint persp_top[5]; - MwPoint persp_right[5]; - - node.x += gap; - - node.height = -c->entries[i].value / (vmax - vmin) * (r.height - space); - node.y = (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space); - - MwDrawRect(handle, &node, color); - - if(type == MwCHART_3D_BAR) { - MwRect node2 = node; - - MwFixRect(&node2); - - persp_top[0] = *(MwPoint*)&node2; - persp_top[1] = *(MwPoint*)&node2; - persp_top[1].x += node2.width; - - persp_top[2] = persp_top[1]; - persp_top[3] = persp_top[0]; - - persp_top[2].x += node2.width / 2; - persp_top[2].y -= node2.width / 2; - - persp_top[3].x += node2.width / 2; - persp_top[3].y -= node2.width / 2; - - persp_top[4] = persp_top[0]; - - MwLLPolygon(handle->lowlevel, persp_top, 4, colorl); - - persp_right[0] = *(MwPoint*)&node2; - persp_right[1] = *(MwPoint*)&node2; - persp_right[0].x += node2.width; - persp_right[1].x += node2.width; - persp_right[1].y += node2.height; - - persp_right[2] = persp_right[1]; - persp_right[3] = persp_right[0]; - - persp_right[2].x += node2.width / 2; - persp_right[2].y -= node2.width / 2; - - persp_right[3].x += node2.width / 2; - persp_right[3].y -= node2.width / 2; - - persp_right[4] = persp_right[0]; - - MwLLPolygon(handle->lowlevel, persp_right, 4, colord); - } - - if(!modern) { - MwDrawRectLine(handle, &node, border); - - if(type == MwCHART_3D_BAR) { - MwLLLine(handle->lowlevel, &persp_top[0], border); - MwLLLine(handle->lowlevel, &persp_top[1], border); - MwLLLine(handle->lowlevel, &persp_top[2], border); - MwLLLine(handle->lowlevel, &persp_top[3], border); - - MwLLLine(handle->lowlevel, &persp_right[0], border); - MwLLLine(handle->lowlevel, &persp_right[1], border); - MwLLLine(handle->lowlevel, &persp_right[2], border); - MwLLLine(handle->lowlevel, &persp_right[3], border); - } - } - - p[0].x = node.x + node.width / 2; - p[0].y = r.height - space / 2; - - MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); - - node.x += node.width; - - MwLLFreeColor(colord); - MwLLFreeColor(colorl); - MwLLFreeColor(color); - } - } else if(type == MwCHART_PIE || type == MwCHART_3D_PIE) { - double sum = 0; - int radius = r.width < r.height ? r.width : r.height; - double cangle = 0; - int k; - double vsquish = type == MwCHART_3D_PIE ? 2 : 1; - MwPoint p2[360 + 1 + 1]; - - for(i = 0; i < arrlen(c->entries); i++) { - if(c->entries[i].value > 0) sum += c->entries[i].value; - } - - for(k = 0; k < 4; k++) { - for(i = 0; i < arrlen(c->entries); i++) { - MwLLColor color; - MwLLColor colorl; - double angle = c->entries[i].value / sum * 360; - int div = angle / PIE_DIV; - int j; - int count; - - if(c->entries[i].value <= 0) continue; - if((k == 0 || k == 1) && type == MwCHART_PIE) continue; - - color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); - colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); - - p2[0].x = r.width / 2; - p2[0].y = r.height / 2; - for(j = 0; j <= div; j++) { - double a = angle / div * j; - - p2[div - j + 1].x = p2[0].x + cos((cangle + a - 90) / 180 * M_PI) * radius / 2; - p2[div - j + 1].y = p2[0].y + sin((cangle + a - 90) / 180 * M_PI) * radius / 2 / vsquish; - } - - count = j + 1; - - if((k == 0 || k == 1) && type == MwCHART_3D_PIE) { - int j; - MwPoint p3[360 + 1 + 1]; - int d = 0; - - for(d = 1; d <= 2; d++) { - for(j = 0; j < count - 1; j++) { - p3[3 + j] = p2[1 + j]; - p3[3 + j].y += radius / 8 / d; - } - - p3[0] = p2[count - 1]; - p3[1] = p2[0]; - p3[2] = p2[1]; - - if(k == 0) { - MwLLPolygon(handle->lowlevel, p3, count + 2, color); - } else if(d == 1 && k == 1) { - for(j = 3; j < count + 1; j++) { - if(!modern) MwLLLine(handle->lowlevel, &p3[j], border); - } - - p2[0] = p2[1]; - p2[0].y += radius / 8; - if(!modern) MwLLLine(handle->lowlevel, p2, border); - } - } - } - - if(k == 2) { - MwLLPolygon(handle->lowlevel, p2, count, type == MwCHART_3D_PIE ? colorl : color); - } else if(k == 3) { - int j; - - p[count] = p2[0]; - for(j = 0; j < count; j++) { - if(!modern) MwLLLine(handle->lowlevel, &p2[j], border); - } - - p2[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; - p2[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4 / vsquish; - - handle->bgcolor = type == MwCHART_3D_PIE ? colorl : color; - - MwDrawText(handle, NULL, p2, c->entries[i].name, MwALIGNMENT_CENTER, border); - } - - cangle += angle; - - MwLLFreeColor(colorl); - MwLLFreeColor(color); - } - } - - if(!modern && type == MwCHART_3D_PIE) { - p[0].x = r.width / 2 - radius / 2; - p[0].y = r.height / 2; - p[1] = p[0]; - p[1].y += radius / 8; - MwLLLine(handle->lowlevel, p, border); - - p[0].x = p[1].x = r.width / 2 + radius / 2; - MwLLLine(handle->lowlevel, p, border); - } - } else if(type == MwCHART_LINE) { - char buf[128]; - MwRect node; - double twidth; - double x = 0; - - for(i = 0; i < arrlen(c->entries); i++) { - int w; - - sprintf(buf, NUMFMT, c->entries[i].value); - - w = MwTextWidth(handle, NULL, buf); - - if(x < w) x = w; - } - - width = 16; - twidth = r.width - x; - - CALC_VMIN_VMAX; - - sprintf(buf, NUMFMT, ovmax); - draw_line(handle, buf, x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - - draw_line(handle, "0", x, (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - - sprintf(buf, NUMFMT, ovmin); - draw_line(handle, buf, x, (r.height - space) - (ovmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - - draw_line(handle, "", x, (r.height - space) - (vmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); - - p[0].x = x; - p[0].y = 0; - - p[1] = p[0]; - p[1].y = r.height - space; - - MwLLLine(handle->lowlevel, p, border); - - for(i = 1; i < arrlen(c->entries); i++) { - p[0].x = x + (r.width - x) / (arrlen(c->entries) + 1) * i; - p[0].y = (r.height - space) - (c->entries[i - 1].value - vmin) / (vmax - vmin) * (r.height - space); - p[1].x = x + (r.width - x) / (arrlen(c->entries) + 1) * (i + 1); - p[1].y = (r.height - space) - (c->entries[i].value - vmin) / (vmax - vmin) * (r.height - space); - - MwLLLine(handle->lowlevel, p, border); - } + switch(type) { + case MwCHART_BAR: + case MwCHART_3D_BAR: + bar_chart(handle, &r, vmin, vmax, space, colors, n, border); + break; + case MwCHART_PIE: + case MwCHART_3D_PIE: + pie_chart(handle, &r, colors, n, border); + break; + case MwCHART_LINE: + line_chart(handle, &r, vmin, vmax, space, border); + break; } MwLLFreeColor(border); From 8d3b707d9e598e9ef08b8edac7d365662c3d0ba2 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 05:14:36 +0900 Subject: [PATCH 088/168] ok --- NTMakefile | 6 +- WatMakefile | 10 +- examples/basic/document.c | 45 + external/md4c.c | 7386 ++++++++++++++++++++++++++++++++++ external/md4c.h | 495 +++ include/Mw/Milsko.h | 1 + include/Mw/StringDefs.h | 1 + include/Mw/Widget/Document.h | 24 + milsko.xml | 1 + pl/rules.pl | 2 + src/widget/document.c | 54 + tools/genmk.pl | 2 +- 12 files changed, 8022 insertions(+), 5 deletions(-) create mode 100644 examples/basic/document.c create mode 100644 external/md4c.c create mode 100644 external/md4c.h create mode 100644 include/Mw/Widget/Document.h create mode 100644 src/widget/document.c diff --git a/NTMakefile b/NTMakefile index 2d41468..d0fc463 100644 --- a/NTMakefile +++ b/NTMakefile @@ -25,6 +25,7 @@ clean: del /f /q external\libz\src\trees.obj del /f /q external\libz\src\uncompr.obj del /f /q external\libz\src\zutil.obj + del /f /q external\md4c.obj del /f /q external\stb_ds.obj del /f /q external\stb_image.obj del /f /q external\stb_truetype.obj @@ -83,6 +84,7 @@ clean: del /f /q src\widget\checkbox.obj del /f /q src\widget\clock.obj del /f /q src\widget\combobox.obj + del /f /q src\widget\document.obj del /f /q src\widget\entry.obj del /f /q src\widget\frame.obj del /f /q src\widget\image.obj @@ -322,8 +324,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index 0b4f73a..ce6792b 100644 --- a/WatMakefile +++ b/WatMakefile @@ -24,6 +24,7 @@ clean: .SYMBOLIC %erase external/libz/src/trees.obj %erase external/libz/src/uncompr.obj %erase external/libz/src/zutil.obj + %erase external/md4c.obj %erase external/stb_ds.obj %erase external/stb_image.obj %erase external/stb_truetype.obj @@ -82,6 +83,7 @@ clean: .SYMBOLIC %erase src/widget/checkbox.obj %erase src/widget/clock.obj %erase src/widget/combobox.obj + %erase src/widget/document.obj %erase src/widget/entry.obj %erase src/widget/frame.obj %erase src/widget/image.obj @@ -321,8 +323,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -356,6 +358,8 @@ external/libz/src/uncompr.obj: external/libz/src/uncompr.c $(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/uncompr.c external/libz/src/zutil.obj: external/libz/src/zutil.c $(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/zutil.c +external/md4c.obj: external/md4c.c + $(CC) $(MW_CFLAGS) -fo=$@ external/md4c.c external/stb_ds.obj: external/stb_ds.c $(CC) $(MW_CFLAGS) -fo=$@ external/stb_ds.c external/stb_image.obj: external/stb_image.c @@ -472,6 +476,8 @@ src/widget/clock.obj: src/widget/clock.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/clock.c src/widget/combobox.obj: src/widget/combobox.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/combobox.c +src/widget/document.obj: src/widget/document.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/document.c src/widget/entry.obj: src/widget/entry.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/entry.c src/widget/frame.obj: src/widget/frame.c diff --git a/examples/basic/document.c b/examples/basic/document.c new file mode 100644 index 0000000..e53339c --- /dev/null +++ b/examples/basic/document.c @@ -0,0 +1,45 @@ +#include + +MwWidget window, viewport, document; + +static void MWAPI resize_window(MwWidget handle, void* user, void* call) { + int width = MwGetInteger(window, MwNwidth); + int height = MwGetInteger(window, MwNheight); + + MwVaApply(viewport, + MwNx, 10, + MwNy, 10, + MwNwidth, width - 20, + MwNheight, height - 20, + NULL); +} + +static void MWAPI resize_document(MwWidget handle, void* user, void* call) { + MwViewportSetSize(viewport, MwGetInteger(document, MwNwidth), MwGetInteger(document, MwNheight)); +} + +int main() { + MwLibraryInit(); + + window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 640, 480, + MwNtitle, "markdown document", + NULL); + + viewport = MwCreateWidget(MwViewportClass, "viewport", window, 0, 0, 0, 0); + + MwVaApply(MwGetParent(MwViewportGetViewport(viewport)), + MwNbackground, "#fff", + MwNforeground, "#000", + NULL); + + document = MwVaCreateWidget(MwDocumentClass, "document", MwViewportGetViewport(viewport), 0, 0, 0, 0, + MwNtext, "# Hello world!\nThis is a test text...", + NULL); + + MwAddUserHandler(window, MwNresizeHandler, resize_window, NULL); + MwAddUserHandler(document, MwNresizeHandler, resize_document, NULL); + + resize_window(window, NULL, NULL); + + MwLoop(window); +} diff --git a/external/md4c.c b/external/md4c.c new file mode 100644 index 0000000..22ab420 --- /dev/null +++ b/external/md4c.c @@ -0,0 +1,7386 @@ +/* + * MD4C: Markdown parser for C + * (https://github.com/mity/md4c) + * + * Copyright (c) 2016-2026 Martin Mitáš + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "md4c.h" + + +/***************************** + *** Miscellaneous Stuff *** + *****************************/ + +/* Make the UTF-8 support the default. */ +#if !defined MD4C_USE_ASCII && !defined MD4C_USE_UTF8 && !defined MD4C_USE_UTF16 + #define MD4C_USE_UTF8 +#endif + +/* Magic for making wide literals with MD4C_USE_UTF16. */ +#ifdef _T + #undef _T +#endif +#if defined MD4C_USE_UTF16 + #define _T(x) L##x +#else + #define _T(x) x +#endif + +/* Misc. macros. */ +#define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(a[0])) + +#define STRINGIZE_(x) #x +#define STRINGIZE(x) STRINGIZE_(x) + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define MD_LOG(msg) \ + do { \ + if(ctx->parser.debug_log != NULL) \ + ctx->parser.debug_log((msg), ctx->userdata); \ + } while(0) + +#ifdef DEBUG + #define MD_ASSERT(cond) \ + do { \ + if(!(cond)) { \ + MD_LOG(__FILE__ ":" STRINGIZE(__LINE__) ": " \ + "Assertion '" STRINGIZE(cond) "' failed."); \ + exit(EXIT_FAILURE); \ + } \ + } while(0) + + #define MD_UNREACHABLE() MD_ASSERT(1 == 0) +#else + #ifdef __GNUC__ + #define MD_ASSERT(cond) do { if(!(cond)) __builtin_unreachable(); } while(0) + #define MD_UNREACHABLE() do { __builtin_unreachable(); } while(0) + #elif defined _MSC_VER && _MSC_VER > 120 + #define MD_ASSERT(cond) do { __assume(cond); } while(0) + #define MD_UNREACHABLE() do { __assume(0); } while(0) + #else + #define MD_ASSERT(cond) do {} while(0) + #define MD_UNREACHABLE() do {} while(0) + #endif +#endif + +/* For falling through case labels in switch statements. */ +#if defined __clang__ && __clang_major__ >= 12 + #define MD_FALLTHROUGH() ;__attribute__((fallthrough)) +#elif defined __GNUC__ && __GNUC__ >= 7 + #define MD_FALLTHROUGH() ;__attribute__((fallthrough)) +#else + #define MD_FALLTHROUGH() ((void)0) +#endif + +/* Suppress "unused parameter" warnings. */ +#define MD_UNUSED(x) ((void)x) + + +/****************************** + *** Some internal limits *** + ******************************/ + +/* We limit code span marks to lower than 32 backticks. This solves the + * pathologic case of too many openers, each of different length: Their + * resolving would be then O(n^2). */ +#define CODESPAN_MARK_MAXLEN 32 + + +/************************ + *** Internal Types *** + ************************/ + +/* These are omnipresent so lets save some typing. */ +#define CHAR MD_CHAR +#define SZ MD_SIZE +#define OFF MD_OFFSET + +typedef struct MD_MARK_tag MD_MARK; +typedef struct MD_BLOCK_tag MD_BLOCK; +typedef struct MD_CONTAINER_tag MD_CONTAINER; +typedef struct MD_REF_DEF_tag MD_REF_DEF; +typedef struct MD_FOOTNOTE_DEF_tag MD_FOOTNOTE_DEF; + +/* Forward declaration; full definition is below with MD_LINE_tag. */ +typedef struct MD_LINE_tag MD_LINE; + +typedef struct MD_LABEL_HASH_ENTRY_tag MD_LABEL_HASH_ENTRY; +struct MD_LABEL_HASH_ENTRY_tag { + const CHAR* label; + SZ label_size; + unsigned hash; +}; + +typedef struct MD_LABEL_HASH_TABLE_tag MD_LABEL_HASH_TABLE; +struct MD_LABEL_HASH_TABLE_tag { + /* Flat array of all records. */ + union { + void* defs; + MD_REF_DEF* ref_defs; + MD_FOOTNOTE_DEF* footnote_defs; + }; + unsigned def_size; + unsigned n_defs; + unsigned alloc_defs; + + /* The hashtable itself, where the actual entries are pointers into the + * array defs[] above. */ + void** buckets; + unsigned n_buckets; +}; + + +/* During analyzes of inline marks, we need to manage stacks of unresolved + * openers of the given type. + * The stack connects the marks via MD_MARK::next; + */ +typedef struct MD_MARKSTACK_tag MD_MARKSTACK; +struct MD_MARKSTACK_tag { + int top; /* -1 if empty. */ +}; + +/* Context propagated through all the parsing. */ +typedef struct MD_CTX_tag MD_CTX; +struct MD_CTX_tag { + /* Immutable stuff (parameters of md_parse()). */ + const CHAR* text; + SZ size; + MD_PARSER parser; + void* userdata; + + /* When this is true, it allows some optimizations. */ + int doc_ends_with_newline; + + /* Helper temporary growing buffer. */ + CHAR* buffer; + unsigned alloc_buffer; + + /* Reference definitions. */ + MD_LABEL_HASH_TABLE ref_def_hashtable; + SZ max_ref_def_output; + + /* Footnote definitions. */ + MD_LABEL_HASH_TABLE footnote_hashtable; + unsigned next_footnote_index; /* 1-based counter for sequential numbering */ + + /* Stack of inline/span markers. + * This is only used for parsing a single block contents but by storing it + * here we may reuse the stack for subsequent blocks; i.e. we have fewer + * (re)allocations. */ + MD_MARK* marks; + int n_marks; + int alloc_marks; + +#if defined MD4C_USE_UTF16 + char mark_char_map[128]; +#else + char mark_char_map[256]; +#endif + + /* For resolving of inline spans. */ + MD_MARKSTACK opener_stacks[20]; +#define ASTERISK_OPENERS_oo_mod3_0 (ctx->opener_stacks[0]) /* Opener-only */ +#define ASTERISK_OPENERS_oo_mod3_1 (ctx->opener_stacks[1]) +#define ASTERISK_OPENERS_oo_mod3_2 (ctx->opener_stacks[2]) +#define ASTERISK_OPENERS_oc_mod3_0 (ctx->opener_stacks[3]) /* Both opener and closer candidate */ +#define ASTERISK_OPENERS_oc_mod3_1 (ctx->opener_stacks[4]) +#define ASTERISK_OPENERS_oc_mod3_2 (ctx->opener_stacks[5]) +#define UNDERSCORE_OPENERS_oo_mod3_0 (ctx->opener_stacks[6]) /* Opener-only */ +#define UNDERSCORE_OPENERS_oo_mod3_1 (ctx->opener_stacks[7]) +#define UNDERSCORE_OPENERS_oo_mod3_2 (ctx->opener_stacks[8]) +#define UNDERSCORE_OPENERS_oc_mod3_0 (ctx->opener_stacks[9]) /* Both opener and closer candidate */ +#define UNDERSCORE_OPENERS_oc_mod3_1 (ctx->opener_stacks[10]) +#define UNDERSCORE_OPENERS_oc_mod3_2 (ctx->opener_stacks[11]) +#define TILDE_OPENERS_1 (ctx->opener_stacks[12]) +#define TILDE_OPENERS_2 (ctx->opener_stacks[13]) +#define BRACKET_OPENERS (ctx->opener_stacks[14]) +#define DOLLAR_OPENERS (ctx->opener_stacks[15]) +#define PIPE_OPENERS (ctx->opener_stacks[16]) +#define CARET_OPENERS (ctx->opener_stacks[17]) +#define EQUAL_OPENERS (ctx->opener_stacks[18]) +#define PLUS_OPENERS (ctx->opener_stacks[19]) + + /* Stack of dummies which need to call free() for pointers stored in them. + * These are constructed during inline parsing and freed after all the block + * is processed (i.e. all callbacks referring those strings are called). */ + MD_MARKSTACK ptr_stack; + + /* For resolving table rows. */ + int n_table_cell_boundaries; + int table_cell_boundaries_head; + int table_cell_boundaries_tail; + + /* For resolving links. */ + int unresolved_link_head; + int unresolved_link_tail; + + /* For resolving raw HTML. */ + OFF html_comment_horizon; + OFF html_proc_instr_horizon; + OFF html_decl_horizon; + OFF html_cdata_horizon; + + /* For block analysis. + * Notes: + * -- It holds MD_BLOCK as well as MD_LINE structures. After each + * MD_BLOCK, its (multiple) MD_LINE(s) follow. + * -- For MD_BLOCK_HTML and MD_BLOCK_CODE, MD_VERBATIMLINE(s) are used + * instead of MD_LINE(s). + */ + void* block_bytes; + MD_BLOCK* current_block; + int n_block_bytes; + int alloc_block_bytes; + + /* Pending count of blank lines not yet reported as MD_BLOCK_BLANK. + * Used only with MD_FLAG_PRESERVEBLANKLINES. */ + unsigned n_blank_lines; + + /* For container block analysis. */ + MD_CONTAINER* containers; + int n_containers; + int alloc_containers; + + /* Minimal indentation to call the block "indented code block". */ + unsigned code_indent_offset; + + /* Contextual info for line analysis. */ + SZ code_fence_length; /* For checking closing fence length. */ + int html_block_type; /* For checking closing raw HTML condition. */ + int last_line_has_list_loosening_effect; + int consecutive_blank_lines; +}; + +enum MD_LINETYPE_tag { + MD_LINE_BLANK, + MD_LINE_HR, + MD_LINE_ATXHEADER, + MD_LINE_SETEXTHEADER, + MD_LINE_SETEXTUNDERLINE, + MD_LINE_INDENTEDCODE, + MD_LINE_FENCEDCODE, + MD_LINE_HTML, + MD_LINE_TEXT, + MD_LINE_TABLE, + MD_LINE_TABLEUNDERLINE +}; +typedef enum MD_LINETYPE_tag MD_LINETYPE; + +typedef struct MD_LINE_ANALYSIS_tag MD_LINE_ANALYSIS; +struct MD_LINE_ANALYSIS_tag { + MD_LINETYPE type; + unsigned data; + int enforce_new_block; + OFF beg; + OFF end; + unsigned indent; /* Indentation level. */ +}; + +struct MD_LINE_tag { + OFF beg; + OFF end; +}; + +typedef struct MD_VERBATIMLINE_tag MD_VERBATIMLINE; +struct MD_VERBATIMLINE_tag { + OFF beg; + OFF end; + OFF indent; +}; + + +/***************** + *** Helpers *** + *****************/ + +/* Character accessors. */ +#define CH(off) (ctx->text[(off)]) +#define STR(off) (ctx->text + (off)) + +/* Character classification. + * Note we assume ASCII compatibility of code points < 128 here. */ +#define ISIN_(ch, ch_min, ch_max) ((ch_min) <= (unsigned)(ch) && (unsigned)(ch) <= (ch_max)) +#define ISANYOF_(ch, palette) ((ch) != _T('\0') && md_strchr((palette), (ch)) != NULL) +#define ISANYOF2_(ch, ch1, ch2) ((ch) == (ch1) || (ch) == (ch2)) +#define ISANYOF3_(ch, ch1, ch2, ch3) ((ch) == (ch1) || (ch) == (ch2) || (ch) == (ch3)) +#define ISASCII_(ch) ((unsigned)(ch) <= 127) +#define ISBLANK_(ch) (ISANYOF2_((ch), _T(' '), _T('\t'))) +#define ISNEWLINE_(ch) (ISANYOF2_((ch), _T('\r'), _T('\n'))) +#define ISWHITESPACE_(ch) (ISBLANK_(ch) || ISANYOF2_((ch), _T('\v'), _T('\f'))) +#define ISCNTRL_(ch) ((unsigned)(ch) <= 31 || (unsigned)(ch) == 127) +#define ISPUNCT_(ch) (ISIN_(ch, 33, 47) || ISIN_(ch, 58, 64) || ISIN_(ch, 91, 96) || ISIN_(ch, 123, 126)) +#define ISUPPER_(ch) (ISIN_(ch, _T('A'), _T('Z'))) +#define ISLOWER_(ch) (ISIN_(ch, _T('a'), _T('z'))) +#define ISALPHA_(ch) (ISUPPER_(ch) || ISLOWER_(ch)) +#define ISDIGIT_(ch) (ISIN_(ch, _T('0'), _T('9'))) +#define ISXDIGIT_(ch) (ISDIGIT_(ch) || ISIN_(ch, _T('A'), _T('F')) || ISIN_(ch, _T('a'), _T('f'))) +#define ISALNUM_(ch) (ISALPHA_(ch) || ISDIGIT_(ch)) + +#define ISANYOF(off, palette) ISANYOF_(CH(off), (palette)) +#define ISANYOF2(off, ch1, ch2) ISANYOF2_(CH(off), (ch1), (ch2)) +#define ISANYOF3(off, ch1, ch2, ch3) ISANYOF3_(CH(off), (ch1), (ch2), (ch3)) +#define ISASCII(off) ISASCII_(CH(off)) +#define ISBLANK(off) ISBLANK_(CH(off)) +#define ISNEWLINE(off) ISNEWLINE_(CH(off)) +#define ISWHITESPACE(off) ISWHITESPACE_(CH(off)) +#define ISCNTRL(off) ISCNTRL_(CH(off)) +#define ISPUNCT(off) ISPUNCT_(CH(off)) +#define ISUPPER(off) ISUPPER_(CH(off)) +#define ISLOWER(off) ISLOWER_(CH(off)) +#define ISALPHA(off) ISALPHA_(CH(off)) +#define ISDIGIT(off) ISDIGIT_(CH(off)) +#define ISXDIGIT(off) ISXDIGIT_(CH(off)) +#define ISALNUM(off) ISALNUM_(CH(off)) + + +#if defined MD4C_USE_UTF16 + #define md_strchr wcschr + #define md_strlen wcslen +#else + #define md_strchr strchr + #define md_strlen strlen +#endif + + +/* Case insensitive check of string equality. */ +static inline int +md_ascii_case_eq(const CHAR* s1, const CHAR* s2, SZ n) +{ + OFF i; + for(i = 0; i < n; i++) { + CHAR ch1 = s1[i]; + CHAR ch2 = s2[i]; + + if(ISLOWER_(ch1)) + ch1 += ('A'-'a'); + if(ISLOWER_(ch2)) + ch2 += ('A'-'a'); + if(ch1 != ch2) + return false; + } + return true; +} + +static inline int +md_ascii_eq(const CHAR* s1, const CHAR* s2, SZ n) +{ + return memcmp(s1, s2, n * sizeof(CHAR)) == 0; +} + +static int +md_text_with_null_replacement(MD_CTX* ctx, MD_TEXTTYPE type, const CHAR* str, SZ size) +{ + OFF off = 0; + int ret = 0; + + while(1) { + while(off < size && str[off] != _T('\0')) + off++; + + if(off > 0) { + ret = ctx->parser.text(type, str, off, ctx->userdata); + if(ret != 0) + return ret; + + str += off; + size -= off; + off = 0; + } + + if(off >= size) + return 0; + + ret = ctx->parser.text(MD_TEXT_NULLCHAR, _T(""), 1, ctx->userdata); + if(ret != 0) + return ret; + off++; + } +} + + +#define MD_CHECK(func) \ + do { \ + ret = (func); \ + if(ret != 0) \ + goto abort; \ + } while(0) + + +#define MD_TEMP_BUFFER(sz) \ + do { \ + if(sz > ctx->alloc_buffer) { \ + CHAR* new_buffer; \ + SZ new_size = ((sz) + (sz) / 2 + 128) & ~127; \ + \ + new_buffer = realloc(ctx->buffer, new_size); \ + if(new_buffer == NULL) { \ + MD_LOG("realloc() failed."); \ + ret = -1; \ + goto abort; \ + } \ + \ + ctx->buffer = new_buffer; \ + ctx->alloc_buffer = new_size; \ + } \ + } while(0) + + +#define MD_ENTER_BLOCK(type, arg) \ + do { \ + ret = ctx->parser.enter_block((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from enter_block() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_LEAVE_BLOCK(type, arg) \ + do { \ + ret = ctx->parser.leave_block((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from leave_block() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_ENTER_SPAN(type, arg) \ + do { \ + ret = ctx->parser.enter_span((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from enter_span() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_LEAVE_SPAN(type, arg) \ + do { \ + ret = ctx->parser.leave_span((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from leave_span() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_TEXT(type, str, size) \ + do { \ + if(size > 0) { \ + ret = ctx->parser.text((type), (str), (size), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from text() callback."); \ + goto abort; \ + } \ + } \ + } while(0) + +#define MD_TEXT_INSECURE(type, str, size) \ + do { \ + if(size > 0) { \ + ret = md_text_with_null_replacement(ctx, type, str, size); \ + if(ret != 0) { \ + MD_LOG("Aborted from text() callback."); \ + goto abort; \ + } \ + } \ + } while(0) + + +/* If the offset falls into a gap between line, we return the following + * line. */ +static const MD_LINE* +md_lookup_line(OFF off, const MD_LINE* lines, MD_SIZE n_lines, MD_SIZE* p_line_index) +{ + MD_SIZE lo, hi; + MD_SIZE pivot; + const MD_LINE* line; + + lo = 0; + hi = n_lines - 1; + while(lo <= hi) { + pivot = (lo + hi) / 2; + line = &lines[pivot]; + + if(off < line->beg) { + if(hi == 0 || lines[hi-1].end < off) { + if(p_line_index != NULL) + *p_line_index = pivot; + return line; + } + hi = pivot - 1; + } else if(off > line->end) { + lo = pivot + 1; + } else { + if(p_line_index != NULL) + *p_line_index = pivot; + return line; + } + } + + return NULL; +} + + +/************************* + *** Unicode Support *** + *************************/ + +typedef struct MD_UNICODE_FOLD_INFO_tag MD_UNICODE_FOLD_INFO; +struct MD_UNICODE_FOLD_INFO_tag { + unsigned codepoints[3]; + unsigned n_codepoints; +}; + + +#if defined MD4C_USE_UTF16 || defined MD4C_USE_UTF8 + /* Binary search over sorted "map" of codepoints. Consecutive sequences + * of codepoints may be encoded in the map by just using the + * (MIN_CODEPOINT | 0x40000000) and (MAX_CODEPOINT | 0x80000000). + * + * Returns index of the found record in the map (in the case of ranges, + * the minimal value is used); or -1 on failure. */ + static int + md_unicode_bsearch__(unsigned codepoint, const unsigned* map, size_t map_size) + { + int beg, end; + int pivot_beg, pivot_end; + + beg = 0; + end = (int) map_size-1; + while(beg <= end) { + /* Pivot may be a range, not just a single value. */ + pivot_beg = pivot_end = (beg + end) / 2; + if(map[pivot_end] & 0x40000000) + pivot_end++; + if(map[pivot_beg] & 0x80000000) + pivot_beg--; + + if(codepoint < (map[pivot_beg] & 0x00ffffff)) + end = pivot_beg - 1; + else if(codepoint > (map[pivot_end] & 0x00ffffff)) + beg = pivot_end + 1; + else + return pivot_beg; + } + + return -1; + } + + static int + md_is_unicode_whitespace__(unsigned codepoint) + { +#define R(cp_min, cp_max) ((cp_min) | 0x40000000), ((cp_max) | 0x80000000) +#define S(cp) (cp) + /* Unicode "Zs" category. + * (generated by scripts/build_whitespace_map.py) */ + static const unsigned WHITESPACE_MAP[] = { + S(0x0020), S(0x00a0), S(0x1680), R(0x2000,0x200a), S(0x202f), S(0x205f), S(0x3000) + }; +#undef R +#undef S + + /* The ASCII ones are the most frequently used ones, also CommonMark + * specification requests few more in this range. */ + if(codepoint <= 0x7f) + return ISWHITESPACE_(codepoint); + + return (md_unicode_bsearch__(codepoint, WHITESPACE_MAP, SIZEOF_ARRAY(WHITESPACE_MAP)) >= 0); + } + + static int + md_is_unicode_punct__(unsigned codepoint) + { +#define R(cp_min, cp_max) ((cp_min) | 0x40000000), ((cp_max) | 0x80000000) +#define S(cp) (cp) + /* Unicode general "P" and "S" categories. + * (generated by scripts/build_punct_map.py) */ + static const unsigned PUNCT_MAP[] = { + R(0x0021,0x002f), R(0x003a,0x0040), R(0x005b,0x0060), R(0x007b,0x007e), R(0x00a1,0x00a9), + R(0x00ab,0x00ac), R(0x00ae,0x00b1), S(0x00b4), R(0x00b6,0x00b8), S(0x00bb), S(0x00bf), S(0x00d7), + S(0x00f7), R(0x02c2,0x02c5), R(0x02d2,0x02df), R(0x02e5,0x02eb), S(0x02ed), R(0x02ef,0x02ff), S(0x0375), + S(0x037e), R(0x0384,0x0385), S(0x0387), S(0x03f6), S(0x0482), R(0x055a,0x055f), R(0x0589,0x058a), + R(0x058d,0x058f), S(0x05be), S(0x05c0), S(0x05c3), S(0x05c6), R(0x05f3,0x05f4), R(0x0606,0x060f), + S(0x061b), R(0x061d,0x061f), R(0x066a,0x066d), S(0x06d4), S(0x06de), S(0x06e9), R(0x06fd,0x06fe), + R(0x0700,0x070d), R(0x07f6,0x07f9), R(0x07fe,0x07ff), R(0x0830,0x083e), S(0x085e), S(0x0888), + R(0x0964,0x0965), S(0x0970), R(0x09f2,0x09f3), R(0x09fa,0x09fb), S(0x09fd), S(0x0a76), R(0x0af0,0x0af1), + S(0x0b70), R(0x0bf3,0x0bfa), S(0x0c77), S(0x0c7f), S(0x0c84), S(0x0d4f), S(0x0d79), S(0x0df4), S(0x0e3f), + S(0x0e4f), R(0x0e5a,0x0e5b), R(0x0f01,0x0f17), R(0x0f1a,0x0f1f), S(0x0f34), S(0x0f36), S(0x0f38), + R(0x0f3a,0x0f3d), S(0x0f85), R(0x0fbe,0x0fc5), R(0x0fc7,0x0fcc), R(0x0fce,0x0fda), R(0x104a,0x104f), + R(0x109e,0x109f), S(0x10fb), R(0x1360,0x1368), R(0x1390,0x1399), S(0x1400), R(0x166d,0x166e), + R(0x169b,0x169c), R(0x16eb,0x16ed), R(0x1735,0x1736), R(0x17d4,0x17d6), R(0x17d8,0x17db), + R(0x1800,0x180a), S(0x1940), R(0x1944,0x1945), R(0x19de,0x19ff), R(0x1a1e,0x1a1f), R(0x1aa0,0x1aa6), + R(0x1aa8,0x1aad), R(0x1b4e,0x1b4f), R(0x1b5a,0x1b6a), R(0x1b74,0x1b7f), R(0x1bfc,0x1bff), + R(0x1c3b,0x1c3f), R(0x1c7e,0x1c7f), R(0x1cc0,0x1cc7), S(0x1cd3), S(0x1fbd), R(0x1fbf,0x1fc1), + R(0x1fcd,0x1fcf), R(0x1fdd,0x1fdf), R(0x1fed,0x1fef), R(0x1ffd,0x1ffe), R(0x2010,0x2027), + R(0x2030,0x205e), R(0x207a,0x207e), R(0x208a,0x208e), R(0x20a0,0x20c4), R(0x2100,0x2101), + R(0x2103,0x2106), R(0x2108,0x2109), S(0x2114), R(0x2116,0x2118), R(0x211e,0x2123), S(0x2125), S(0x2127), + S(0x2129), S(0x212e), R(0x213a,0x213b), R(0x2140,0x2144), R(0x214a,0x214d), S(0x214f), R(0x218a,0x218b), + R(0x2190,0x2429), R(0x2440,0x244a), R(0x249c,0x24e9), R(0x2500,0x2775), R(0x2794,0x2b73), + R(0x2b76,0x2bff), R(0x2ce5,0x2cea), R(0x2cf9,0x2cfc), R(0x2cfe,0x2cff), S(0x2d70), R(0x2e00,0x2e2e), + R(0x2e30,0x2e5d), R(0x2e60,0x2e63), R(0x2e80,0x2e99), R(0x2e9b,0x2ef3), R(0x2f00,0x2fd5), + R(0x2ff0,0x2fff), R(0x3001,0x3004), R(0x3008,0x3020), S(0x3030), R(0x3036,0x3037), R(0x303d,0x303f), + R(0x309b,0x309c), S(0x30a0), S(0x30fb), R(0x3190,0x3191), R(0x3196,0x319f), R(0x31c0,0x31e5), S(0x31ef), + R(0x3200,0x321e), R(0x322a,0x3247), S(0x3250), R(0x3260,0x327f), R(0x328a,0x32b0), R(0x32c0,0x33ff), + R(0x4dc0,0x4dff), R(0xa490,0xa4c6), R(0xa4fe,0xa4ff), R(0xa60d,0xa60f), S(0xa673), S(0xa67e), + R(0xa6f2,0xa6f7), R(0xa700,0xa716), R(0xa720,0xa721), R(0xa789,0xa78a), R(0xa828,0xa82b), + R(0xa836,0xa839), R(0xa874,0xa877), R(0xa8ce,0xa8cf), R(0xa8f8,0xa8fa), S(0xa8fc), R(0xa92e,0xa92f), + S(0xa95f), R(0xa9c1,0xa9cd), R(0xa9de,0xa9df), R(0xaa5c,0xaa5f), R(0xaa77,0xaa79), R(0xaade,0xaadf), + R(0xaaf0,0xaaf1), S(0xab5b), R(0xab6a,0xab6b), S(0xabeb), S(0xfb29), R(0xfbb2,0xfbd2), R(0xfd3e,0xfd4f), + R(0xfd90,0xfd91), R(0xfdc8,0xfdcf), R(0xfdfc,0xfdff), R(0xfe10,0xfe19), R(0xfe30,0xfe52), + R(0xfe54,0xfe66), R(0xfe68,0xfe6b), R(0xff01,0xff0f), R(0xff1a,0xff20), R(0xff3b,0xff40), + R(0xff5b,0xff65), R(0xffe0,0xffe6), R(0xffe8,0xffee), R(0xfffc,0xfffd), R(0x10100,0x10102), + R(0x10137,0x1013f), R(0x10179,0x10189), R(0x1018c,0x1018e), R(0x10190,0x1019c), S(0x101a0), + R(0x101d0,0x101fc), S(0x1039f), S(0x103d0), S(0x1056f), S(0x10857), R(0x10877,0x10878), S(0x1091f), + S(0x1093f), R(0x10a50,0x10a58), S(0x10a7f), S(0x10ac8), R(0x10af0,0x10af6), R(0x10b39,0x10b3f), + R(0x10b99,0x10b9c), S(0x10d6e), R(0x10d8e,0x10d8f), S(0x10ead), R(0x10ec9,0x10eca), R(0x10ed0,0x10ed8), + R(0x10f55,0x10f59), R(0x10f86,0x10f89), R(0x11047,0x1104d), R(0x110bb,0x110bc), R(0x110be,0x110c1), + R(0x11140,0x11143), R(0x11174,0x11175), R(0x111c5,0x111c8), S(0x111cd), S(0x111db), R(0x111dd,0x111df), + R(0x11238,0x1123d), S(0x112a9), R(0x113d4,0x113d5), R(0x113d7,0x113d8), R(0x1144b,0x1144f), + R(0x1145a,0x1145b), S(0x1145d), S(0x114c6), R(0x115c1,0x115d7), R(0x11641,0x11643), R(0x11660,0x1166c), + S(0x116b9), R(0x1173c,0x1173f), S(0x1183b), R(0x11944,0x11946), S(0x119e2), R(0x11a3f,0x11a46), + R(0x11a9a,0x11a9c), R(0x11a9e,0x11aa2), R(0x11b00,0x11b09), S(0x11be1), R(0x11c41,0x11c45), + R(0x11c70,0x11c71), R(0x11ef7,0x11ef8), R(0x11f43,0x11f4f), R(0x11fd5,0x11ff1), S(0x11fff), + R(0x12470,0x12474), R(0x12ff1,0x12ff2), R(0x16a6e,0x16a6f), S(0x16af5), R(0x16b37,0x16b3f), + R(0x16b44,0x16b45), R(0x16d6d,0x16d6f), R(0x16e97,0x16e9a), S(0x16fe2), S(0x1bc9c), S(0x1bc9f), + R(0x1cc00,0x1ccef), R(0x1ccfa,0x1ccfc), R(0x1cd00,0x1ceb3), R(0x1ceba,0x1ced0), R(0x1ced2,0x1ced4), + R(0x1cedd,0x1cefd), R(0x1cf50,0x1cfc3), R(0x1d000,0x1d0f5), R(0x1d100,0x1d126), R(0x1d129,0x1d164), + R(0x1d16a,0x1d16c), R(0x1d183,0x1d184), R(0x1d18c,0x1d1a9), R(0x1d1ae,0x1d241), S(0x1d245), + R(0x1d253,0x1d25a), R(0x1d25d,0x1d25e), R(0x1d260,0x1d27f), R(0x1d300,0x1d356), S(0x1d6c1), S(0x1d6db), + S(0x1d6fb), S(0x1d715), S(0x1d735), S(0x1d74f), S(0x1d76f), S(0x1d789), S(0x1d7a9), S(0x1d7c3), + R(0x1d800,0x1d9ff), R(0x1da37,0x1da3a), R(0x1da6d,0x1da74), R(0x1da76,0x1da83), R(0x1da85,0x1da8b), + R(0x1db00,0x1db1c), S(0x1e14f), S(0x1e2ff), S(0x1e5ff), R(0x1e95e,0x1e95f), S(0x1ecac), S(0x1ecb0), + S(0x1ed2e), R(0x1eef0,0x1eef1), R(0x1f000,0x1f02b), R(0x1f030,0x1f093), R(0x1f0a0,0x1f0ae), + R(0x1f0b1,0x1f0bf), R(0x1f0c1,0x1f0cf), R(0x1f0d1,0x1f0f5), R(0x1f10d,0x1f1ae), R(0x1f1e6,0x1f202), + R(0x1f210,0x1f23b), R(0x1f240,0x1f248), R(0x1f250,0x1f251), R(0x1f260,0x1f265), R(0x1f300,0x1f6d9), + R(0x1f6dc,0x1f6ec), R(0x1f6f0,0x1f6fc), R(0x1f700,0x1f7db), R(0x1f7e0,0x1f7eb), R(0x1f7f0,0x1f80b), + R(0x1f810,0x1f847), R(0x1f850,0x1f859), R(0x1f860,0x1f887), R(0x1f890,0x1f8ad), R(0x1f8b0,0x1f8bb), + R(0x1f8c0,0x1f8c1), R(0x1f8d0,0x1f8d8), R(0x1f900,0x1fa57), R(0x1fa60,0x1fa6d), R(0x1fa70,0x1fa7c), + R(0x1fa80,0x1fac6), S(0x1fac8), R(0x1facc,0x1fadd), R(0x1fadf,0x1faeb), R(0x1faef,0x1fafa), + R(0x1fb00,0x1fb92), R(0x1fb94,0x1fbef), S(0x1fbfa) + }; +#undef R +#undef S + + /* The ASCII ones are the most frequently used ones, also CommonMark + * specification requests few more in this range. */ + if(codepoint <= 0x7f) + return ISPUNCT_(codepoint); + + return (md_unicode_bsearch__(codepoint, PUNCT_MAP, SIZEOF_ARRAY(PUNCT_MAP)) >= 0); + } + + static void + md_get_unicode_fold_info(unsigned codepoint, MD_UNICODE_FOLD_INFO* info) + { +#define R(cp_min, cp_max) ((cp_min) | 0x40000000), ((cp_max) | 0x80000000) +#define S(cp) (cp) + /* Unicode "Pc", "Pd", "Pe", "Pf", "Pi", "Po", "Ps" categories. + * (generated by scripts/build_folding_map.py) */ + static const unsigned FOLD_MAP_1[] = { + R(0x0041,0x005a), S(0x00b5), R(0x00c0,0x00d6), R(0x00d8,0x00de), R(0x0100,0x012e), R(0x0132,0x0136), + R(0x0139,0x0147), R(0x014a,0x0176), S(0x0178), R(0x0179,0x017d), S(0x017f), S(0x0181), S(0x0182), + S(0x0184), S(0x0186), S(0x0187), S(0x0189), S(0x018a), S(0x018b), S(0x018e), S(0x018f), S(0x0190), + S(0x0191), S(0x0193), S(0x0194), S(0x0196), S(0x0197), S(0x0198), S(0x019c), S(0x019d), S(0x019f), + R(0x01a0,0x01a4), S(0x01a6), S(0x01a7), S(0x01a9), S(0x01ac), S(0x01ae), S(0x01af), S(0x01b1), S(0x01b2), + S(0x01b3), S(0x01b5), S(0x01b7), S(0x01b8), S(0x01bc), S(0x01c4), S(0x01c5), S(0x01c7), S(0x01c8), + S(0x01ca), R(0x01cb,0x01db), R(0x01de,0x01ee), S(0x01f1), S(0x01f2), S(0x01f4), S(0x01f6), S(0x01f7), + R(0x01f8,0x021e), S(0x0220), R(0x0222,0x0232), S(0x023a), S(0x023b), S(0x023d), S(0x023e), S(0x0241), + S(0x0243), S(0x0244), S(0x0245), R(0x0246,0x024e), S(0x0345), S(0x0370), S(0x0372), S(0x0376), S(0x037f), + S(0x0386), R(0x0388,0x038a), S(0x038c), S(0x038e), S(0x038f), R(0x0391,0x03a1), R(0x03a3,0x03ab), + S(0x03c2), S(0x03cf), S(0x03d0), S(0x03d1), S(0x03d5), S(0x03d6), R(0x03d8,0x03ee), S(0x03f0), S(0x03f1), + S(0x03f4), S(0x03f5), S(0x03f7), S(0x03f9), S(0x03fa), R(0x03fd,0x03ff), R(0x0400,0x040f), + R(0x0410,0x042f), R(0x0460,0x0480), R(0x048a,0x04be), S(0x04c0), R(0x04c1,0x04cd), R(0x04d0,0x052e), + R(0x0531,0x0556), R(0x10a0,0x10c5), S(0x10c7), S(0x10cd), R(0x13f8,0x13fd), S(0x1c80), S(0x1c81), + S(0x1c82), S(0x1c83), S(0x1c84), S(0x1c85), S(0x1c86), S(0x1c87), S(0x1c88), S(0x1c89), R(0x1c90,0x1cba), + R(0x1cbd,0x1cbf), R(0x1e00,0x1e94), S(0x1e9b), R(0x1ea0,0x1efe), R(0x1f08,0x1f0f), R(0x1f18,0x1f1d), + R(0x1f28,0x1f2f), R(0x1f38,0x1f3f), R(0x1f48,0x1f4d), S(0x1f59), S(0x1f5b), S(0x1f5d), S(0x1f5f), + R(0x1f68,0x1f6f), S(0x1fb8), S(0x1fb9), S(0x1fba), S(0x1fbb), S(0x1fbe), R(0x1fc8,0x1fcb), S(0x1fd8), + S(0x1fd9), S(0x1fda), S(0x1fdb), S(0x1fe8), S(0x1fe9), S(0x1fea), S(0x1feb), S(0x1fec), S(0x1ff8), + S(0x1ff9), S(0x1ffa), S(0x1ffb), S(0x2126), S(0x212a), S(0x212b), S(0x2132), R(0x2160,0x216f), S(0x2183), + R(0x24b6,0x24cf), R(0x2c00,0x2c2f), S(0x2c60), S(0x2c62), S(0x2c63), S(0x2c64), R(0x2c67,0x2c6b), + S(0x2c6d), S(0x2c6e), S(0x2c6f), S(0x2c70), S(0x2c72), S(0x2c75), S(0x2c7e), S(0x2c7f), R(0x2c80,0x2ce2), + S(0x2ceb), S(0x2ced), S(0x2cf2), R(0xa640,0xa66c), R(0xa680,0xa69a), R(0xa722,0xa72e), R(0xa732,0xa76e), + S(0xa779), S(0xa77b), S(0xa77d), R(0xa77e,0xa786), S(0xa78b), S(0xa78d), S(0xa790), S(0xa792), + R(0xa796,0xa7a8), S(0xa7aa), S(0xa7ab), S(0xa7ac), S(0xa7ad), S(0xa7ae), S(0xa7b0), S(0xa7b1), S(0xa7b2), + S(0xa7b3), R(0xa7b4,0xa7c2), S(0xa7c4), S(0xa7c5), S(0xa7c6), S(0xa7c7), S(0xa7c9), S(0xa7cb), + R(0xa7cc,0xa7da), S(0xa7dc), S(0xa7dd), S(0xa7e2), S(0xa7f5), S(0xab6c), S(0xab6d), R(0xab70,0xabbf), + R(0xff21,0xff3a), R(0x10400,0x10427), R(0x104b0,0x104d3), R(0x10570,0x1057a), R(0x1057c,0x1058a), + R(0x1058c,0x10592), S(0x10594), S(0x10595), R(0x10c80,0x10cb2), R(0x10d50,0x10d65), R(0x118a0,0x118bf), + R(0x16e40,0x16e5f), R(0x16ea0,0x16eb8), S(0x1df40), S(0x1df48), S(0x1df4a), S(0x1df4d), S(0x1df51), + R(0x1df68,0x1df6e), R(0x1df72,0x1df7e), R(0x1e900,0x1e921) + }; + static const unsigned FOLD_MAP_1_DATA[] = { + 0x0061, 0x007a, 0x03bc, 0x00e0, 0x00f6, 0x00f8, 0x00fe, 0x0101, 0x012f, 0x0133, 0x0137, 0x013a, 0x0148, + 0x014b, 0x0177, 0x00ff, 0x017a, 0x017e, 0x0073, 0x0253, 0x0183, 0x0185, 0x0254, 0x0188, 0x0256, 0x0257, + 0x018c, 0x01dd, 0x0259, 0x025b, 0x0192, 0x0260, 0x0263, 0x0269, 0x0268, 0x0199, 0x026f, 0x0272, 0x0275, + 0x01a1, 0x01a5, 0x0280, 0x01a8, 0x0283, 0x01ad, 0x0288, 0x01b0, 0x028a, 0x028b, 0x01b4, 0x01b6, 0x0292, + 0x01b9, 0x01bd, 0x01c6, 0x01c6, 0x01c9, 0x01c9, 0x01cc, 0x01cc, 0x01dc, 0x01df, 0x01ef, 0x01f3, 0x01f3, + 0x01f5, 0x0195, 0x01bf, 0x01f9, 0x021f, 0x019e, 0x0223, 0x0233, 0x2c65, 0x023c, 0x019a, 0x2c66, 0x0242, + 0x0180, 0x0289, 0x028c, 0x0247, 0x024f, 0x03b9, 0x0371, 0x0373, 0x0377, 0x03f3, 0x03ac, 0x03ad, 0x03af, + 0x03cc, 0x03cd, 0x03ce, 0x03b1, 0x03c1, 0x03c3, 0x03cb, 0x03c3, 0x03d7, 0x03b2, 0x03b8, 0x03c6, 0x03c0, + 0x03d9, 0x03ef, 0x03ba, 0x03c1, 0x03b8, 0x03b5, 0x03f8, 0x03f2, 0x03fb, 0x037b, 0x037d, 0x0450, 0x045f, + 0x0430, 0x044f, 0x0461, 0x0481, 0x048b, 0x04bf, 0x04cf, 0x04c2, 0x04ce, 0x04d1, 0x052f, 0x0561, 0x0586, + 0x2d00, 0x2d25, 0x2d27, 0x2d2d, 0x13f0, 0x13f5, 0x0432, 0x0434, 0x043e, 0x0441, 0x0442, 0x0442, 0x044a, + 0x0463, 0xa64b, 0x1c8a, 0x10d0, 0x10fa, 0x10fd, 0x10ff, 0x1e01, 0x1e95, 0x1e61, 0x1ea1, 0x1eff, 0x1f00, + 0x1f07, 0x1f10, 0x1f15, 0x1f20, 0x1f27, 0x1f30, 0x1f37, 0x1f40, 0x1f45, 0x1f51, 0x1f53, 0x1f55, 0x1f57, + 0x1f60, 0x1f67, 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x03b9, 0x1f72, 0x1f75, 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, + 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x03c9, 0x006b, 0x00e5, 0x214e, + 0x2170, 0x217f, 0x2184, 0x24d0, 0x24e9, 0x2c30, 0x2c5f, 0x2c61, 0x026b, 0x1d7d, 0x027d, 0x2c68, 0x2c6c, + 0x0251, 0x0271, 0x0250, 0x0252, 0x2c73, 0x2c76, 0x023f, 0x0240, 0x2c81, 0x2ce3, 0x2cec, 0x2cee, 0x2cf3, + 0xa641, 0xa66d, 0xa681, 0xa69b, 0xa723, 0xa72f, 0xa733, 0xa76f, 0xa77a, 0xa77c, 0x1d79, 0xa77f, 0xa787, + 0xa78c, 0x0265, 0xa791, 0xa793, 0xa797, 0xa7a9, 0x0266, 0x025c, 0x0261, 0x026c, 0x026a, 0x029e, 0x0287, + 0x029d, 0xab53, 0xa7b5, 0xa7c3, 0xa794, 0x0282, 0x1d8e, 0xa7c8, 0xa7ca, 0x0264, 0xa7cd, 0xa7db, 0x019b, + 0x0277, 0x027c, 0xa7f6, 0xab4b, 0xab4c, 0x13a0, 0x13ef, 0xff41, 0xff5a, 0x10428, 0x1044f, 0x104d8, + 0x104fb, 0x10597, 0x105a1, 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, 0x10cc0, 0x10cf2, + 0x10d70, 0x10d85, 0x118c0, 0x118df, 0x16e60, 0x16e7f, 0x16ebb, 0x16ed3, 0x1df41, 0x1df49, 0x1df4b, + 0x1df4e, 0x1df52, 0x1df69, 0x1df6f, 0x1df73, 0x1df7f, 0x1e922, 0x1e943 + }; + static const unsigned FOLD_MAP_2[] = { + S(0x00df), S(0x0130), S(0x0149), S(0x01f0), S(0x0587), S(0x1e96), S(0x1e97), S(0x1e98), S(0x1e99), + S(0x1e9a), S(0x1e9e), S(0x1f50), R(0x1f80,0x1f87), R(0x1f88,0x1f8f), R(0x1f90,0x1f97), R(0x1f98,0x1f9f), + R(0x1fa0,0x1fa7), R(0x1fa8,0x1faf), S(0x1fb2), S(0x1fb3), S(0x1fb4), S(0x1fb6), S(0x1fbc), S(0x1fc2), + S(0x1fc3), S(0x1fc4), S(0x1fc6), S(0x1fcc), S(0x1fd6), S(0x1fe4), S(0x1fe6), S(0x1ff2), S(0x1ff3), + S(0x1ff4), S(0x1ff6), S(0x1ffc), S(0xfb00), S(0xfb01), S(0xfb02), S(0xfb05), S(0xfb06), S(0xfb13), + S(0xfb14), S(0xfb15), S(0xfb16), S(0xfb17), S(0x1df95) + }; + static const unsigned FOLD_MAP_2_DATA[] = { + 0x0073,0x0073, 0x0069,0x0307, 0x02bc,0x006e, 0x006a,0x030c, 0x0565,0x0582, 0x0068,0x0331, 0x0074,0x0308, + 0x0077,0x030a, 0x0079,0x030a, 0x0061,0x02be, 0x0073,0x0073, 0x03c5,0x0313, 0x1f00,0x03b9, 0x1f07,0x03b9, + 0x1f00,0x03b9, 0x1f07,0x03b9, 0x1f20,0x03b9, 0x1f27,0x03b9, 0x1f20,0x03b9, 0x1f27,0x03b9, 0x1f60,0x03b9, + 0x1f67,0x03b9, 0x1f60,0x03b9, 0x1f67,0x03b9, 0x1f70,0x03b9, 0x03b1,0x03b9, 0x03ac,0x03b9, 0x03b1,0x0342, + 0x03b1,0x03b9, 0x1f74,0x03b9, 0x03b7,0x03b9, 0x03ae,0x03b9, 0x03b7,0x0342, 0x03b7,0x03b9, 0x03b9,0x0342, + 0x03c1,0x0313, 0x03c5,0x0342, 0x1f7c,0x03b9, 0x03c9,0x03b9, 0x03ce,0x03b9, 0x03c9,0x0342, 0x03c9,0x03b9, + 0x0066,0x0066, 0x0066,0x0069, 0x0066,0x006c, 0x0073,0x0074, 0x0073,0x0074, 0x0574,0x0576, 0x0574,0x0565, + 0x0574,0x056b, 0x057e,0x0576, 0x0574,0x056d, 0x0073,0x0073 + }; + static const unsigned FOLD_MAP_3[] = { + S(0x0390), S(0x03b0), S(0x1f52), S(0x1f54), S(0x1f56), S(0x1fb7), S(0x1fc7), S(0x1fd2), S(0x1fd3), + S(0x1fd7), S(0x1fe2), S(0x1fe3), S(0x1fe7), S(0x1ff7), S(0xfb03), S(0xfb04) + }; + static const unsigned FOLD_MAP_3_DATA[] = { + 0x03b9,0x0308,0x0301, 0x03c5,0x0308,0x0301, 0x03c5,0x0313,0x0300, 0x03c5,0x0313,0x0301, + 0x03c5,0x0313,0x0342, 0x03b1,0x0342,0x03b9, 0x03b7,0x0342,0x03b9, 0x03b9,0x0308,0x0300, + 0x03b9,0x0308,0x0301, 0x03b9,0x0308,0x0342, 0x03c5,0x0308,0x0300, 0x03c5,0x0308,0x0301, + 0x03c5,0x0308,0x0342, 0x03c9,0x0342,0x03b9, 0x0066,0x0066,0x0069, 0x0066,0x0066,0x006c + }; +#undef R +#undef S + static const struct { + const unsigned* map; + const unsigned* data; + size_t map_size; + unsigned n_codepoints; + } FOLD_MAP_LIST[] = { + { FOLD_MAP_1, FOLD_MAP_1_DATA, SIZEOF_ARRAY(FOLD_MAP_1), 1 }, + { FOLD_MAP_2, FOLD_MAP_2_DATA, SIZEOF_ARRAY(FOLD_MAP_2), 2 }, + { FOLD_MAP_3, FOLD_MAP_3_DATA, SIZEOF_ARRAY(FOLD_MAP_3), 3 } + }; + + int i; + + /* Fast path for ASCII characters. */ + if(codepoint <= 0x7f) { + info->codepoints[0] = codepoint; + if(ISUPPER_(codepoint)) + info->codepoints[0] += 'a' - 'A'; + info->n_codepoints = 1; + return; + } + + /* Try to locate the codepoint in any of the maps. */ + for(i = 0; i < (int) SIZEOF_ARRAY(FOLD_MAP_LIST); i++) { + int index; + + index = md_unicode_bsearch__(codepoint, FOLD_MAP_LIST[i].map, FOLD_MAP_LIST[i].map_size); + if(index >= 0) { + /* Found the mapping. */ + unsigned n_codepoints = FOLD_MAP_LIST[i].n_codepoints; + const unsigned* map = FOLD_MAP_LIST[i].map; + const unsigned* codepoints = FOLD_MAP_LIST[i].data + (index * n_codepoints); + + memcpy(info->codepoints, codepoints, sizeof(unsigned) * n_codepoints); + info->n_codepoints = n_codepoints; + + if(FOLD_MAP_LIST[i].map[index] != codepoint) { + /* The found mapping maps whole range of codepoints, + * i.e. we have to offset info->codepoints[0] accordingly. */ + if((map[index] & 0x00ffffff)+1 == codepoints[0]) { + /* Alternating type of the range. */ + info->codepoints[0] = codepoint + ((codepoint & 0x1) == (map[index] & 0x1) ? 1 : 0); + } else { + /* Range to range kind of mapping. */ + info->codepoints[0] += (codepoint - (map[index] & 0x00ffffff)); + } + } + + return; + } + } + + /* No mapping found. Map the codepoint to itself. */ + info->codepoints[0] = codepoint; + info->n_codepoints = 1; + } +#endif + + +#if defined MD4C_USE_UTF16 + #define IS_UTF16_SURROGATE_HI(word) (((WORD)(word) & 0xfc00) == 0xd800) + #define IS_UTF16_SURROGATE_LO(word) (((WORD)(word) & 0xfc00) == 0xdc00) + #define UTF16_DECODE_SURROGATE(hi, lo) (0x10000 + ((((unsigned)(hi) & 0x3ff) << 10) | (((unsigned)(lo) & 0x3ff) << 0))) + + static unsigned + md_decode_utf16le__(const CHAR* str, SZ str_size, SZ* p_size) + { + if(IS_UTF16_SURROGATE_HI(str[0])) { + if(1 < str_size && IS_UTF16_SURROGATE_LO(str[1])) { + if(p_size != NULL) + *p_size = 2; + return UTF16_DECODE_SURROGATE(str[0], str[1]); + } + } + + if(p_size != NULL) + *p_size = 1; + return str[0]; + } + + static unsigned + md_decode_utf16le_before__(MD_CTX* ctx, OFF off) + { + if(off > 2 && IS_UTF16_SURROGATE_HI(CH(off-2)) && IS_UTF16_SURROGATE_LO(CH(off-1))) + return UTF16_DECODE_SURROGATE(CH(off-2), CH(off-1)); + + return CH(off-1); + } + + /* No whitespace uses surrogates, so no decoding needed here. */ + #define ISUNICODEWHITESPACE_(codepoint) md_is_unicode_whitespace__(codepoint) + #define ISUNICODEWHITESPACE(off) md_is_unicode_whitespace__(CH(off)) + #define ISUNICODEWHITESPACEBEFORE(off) md_is_unicode_whitespace__(CH((off)-1)) + + #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf16le__(STR(off), ctx->size - (off), NULL)) + #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf16le_before__(ctx, off)) + + static inline int + md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size) + { + return md_decode_utf16le__(str+off, str_size-off, p_char_size); + } +#elif defined MD4C_USE_UTF8 + #define IS_UTF8_LEAD1(byte) ((unsigned char)(byte) <= 0x7f) + #define IS_UTF8_LEAD2(byte) (((unsigned char)(byte) & 0xe0) == 0xc0) + #define IS_UTF8_LEAD3(byte) (((unsigned char)(byte) & 0xf0) == 0xe0) + #define IS_UTF8_LEAD4(byte) (((unsigned char)(byte) & 0xf8) == 0xf0) + #define IS_UTF8_TAIL(byte) (((unsigned char)(byte) & 0xc0) == 0x80) + + static unsigned + md_decode_utf8__(const CHAR* str, SZ str_size, SZ* p_size) + { + if(!IS_UTF8_LEAD1(str[0])) { + if(IS_UTF8_LEAD2(str[0])) { + if(1 < str_size && IS_UTF8_TAIL(str[1])) { + if(p_size != NULL) + *p_size = 2; + + return (((unsigned int)str[0] & 0x1f) << 6) | + (((unsigned int)str[1] & 0x3f) << 0); + } + } else if(IS_UTF8_LEAD3(str[0])) { + if(2 < str_size && IS_UTF8_TAIL(str[1]) && IS_UTF8_TAIL(str[2])) { + if(p_size != NULL) + *p_size = 3; + + return (((unsigned int)str[0] & 0x0f) << 12) | + (((unsigned int)str[1] & 0x3f) << 6) | + (((unsigned int)str[2] & 0x3f) << 0); + } + } else if(IS_UTF8_LEAD4(str[0])) { + if(3 < str_size && IS_UTF8_TAIL(str[1]) && IS_UTF8_TAIL(str[2]) && IS_UTF8_TAIL(str[3])) { + if(p_size != NULL) + *p_size = 4; + + return (((unsigned int)str[0] & 0x07) << 18) | + (((unsigned int)str[1] & 0x3f) << 12) | + (((unsigned int)str[2] & 0x3f) << 6) | + (((unsigned int)str[3] & 0x3f) << 0); + } + } + } + + if(p_size != NULL) + *p_size = 1; + return (unsigned) str[0]; + } + + static unsigned + md_decode_utf8_before__(MD_CTX* ctx, OFF off) + { + if(!IS_UTF8_LEAD1(CH(off-1))) { + if(off > 1 && IS_UTF8_LEAD2(CH(off-2)) && IS_UTF8_TAIL(CH(off-1))) + return (((unsigned int)CH(off-2) & 0x1f) << 6) | + (((unsigned int)CH(off-1) & 0x3f) << 0); + + if(off > 2 && IS_UTF8_LEAD3(CH(off-3)) && IS_UTF8_TAIL(CH(off-2)) && IS_UTF8_TAIL(CH(off-1))) + return (((unsigned int)CH(off-3) & 0x0f) << 12) | + (((unsigned int)CH(off-2) & 0x3f) << 6) | + (((unsigned int)CH(off-1) & 0x3f) << 0); + + if(off > 3 && IS_UTF8_LEAD4(CH(off-4)) && IS_UTF8_TAIL(CH(off-3)) && IS_UTF8_TAIL(CH(off-2)) && IS_UTF8_TAIL(CH(off-1))) + return (((unsigned int)CH(off-4) & 0x07) << 18) | + (((unsigned int)CH(off-3) & 0x3f) << 12) | + (((unsigned int)CH(off-2) & 0x3f) << 6) | + (((unsigned int)CH(off-1) & 0x3f) << 0); + } + + return (unsigned) CH(off-1); + } + + #define ISUNICODEWHITESPACE_(codepoint) md_is_unicode_whitespace__(codepoint) + #define ISUNICODEWHITESPACE(off) md_is_unicode_whitespace__(md_decode_utf8__(STR(off), ctx->size - (off), NULL)) + #define ISUNICODEWHITESPACEBEFORE(off) md_is_unicode_whitespace__(md_decode_utf8_before__(ctx, off)) + + #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf8__(STR(off), ctx->size - (off), NULL)) + #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf8_before__(ctx, off)) + + static inline unsigned + md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size) + { + return md_decode_utf8__(str+off, str_size-off, p_char_size); + } +#else + #define ISUNICODEWHITESPACE_(codepoint) ISWHITESPACE_(codepoint) + #define ISUNICODEWHITESPACE(off) ISWHITESPACE(off) + #define ISUNICODEWHITESPACEBEFORE(off) ISWHITESPACE((off)-1) + + #define ISUNICODEPUNCT(off) ISPUNCT(off) + #define ISUNICODEPUNCTBEFORE(off) ISPUNCT((off)-1) + + static inline void + md_get_unicode_fold_info(unsigned codepoint, MD_UNICODE_FOLD_INFO* info) + { + info->codepoints[0] = codepoint; + if(ISUPPER_(codepoint)) + info->codepoints[0] += 'a' - 'A'; + info->n_codepoints = 1; + } + + static inline unsigned + md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_size) + { + MD_UNUSED(str_size); + *p_size = 1; + return (unsigned) str[off]; + } +#endif + + +/************************************* + *** Helper string manipulations *** + *************************************/ + +/* Fill buffer with copy of the string between 'beg' and 'end' but replace any + * line breaks with given replacement character. + * + * NOTE: Caller is responsible to make sure the buffer is large enough. + * (Given the output is always shorter than input, (end - beg) is good idea + * what the caller should allocate.) + */ +static void +md_merge_lines(MD_CTX* ctx, OFF beg, OFF end, const MD_LINE* lines, MD_SIZE n_lines, + CHAR line_break_replacement_char, CHAR* buffer, SZ* p_size) +{ + CHAR* ptr = buffer; + int line_index = 0; + OFF off = beg; + + MD_UNUSED(n_lines); + + while(1) { + const MD_LINE* line = &lines[line_index]; + OFF line_end = line->end; + if(end < line_end) + line_end = end; + + while(off < line_end) { + *ptr = CH(off); + ptr++; + off++; + } + + if(off >= end) { + *p_size = (MD_SIZE)(ptr - buffer); + return; + } + + *ptr = line_break_replacement_char; + ptr++; + + line_index++; + off = lines[line_index].beg; + } +} + +/* Wrapper of md_merge_lines() which allocates new buffer for the output string. + */ +static int +md_merge_lines_alloc(MD_CTX* ctx, OFF beg, OFF end, const MD_LINE* lines, MD_SIZE n_lines, + CHAR line_break_replacement_char, CHAR** p_str, SZ* p_size) +{ + CHAR* buffer; + + buffer = (CHAR*) malloc(sizeof(CHAR) * (end - beg)); + if(buffer == NULL) { + MD_LOG("malloc() failed."); + return -1; + } + + md_merge_lines(ctx, beg, end, lines, n_lines, + line_break_replacement_char, buffer, p_size); + + *p_str = buffer; + return 0; +} + +static OFF +md_skip_unicode_whitespace(const CHAR* label, OFF off, SZ size) +{ + SZ char_size; + unsigned codepoint; + + while(off < size) { + codepoint = md_decode_unicode(label, off, size, &char_size); + if(!ISUNICODEWHITESPACE_(codepoint) && !ISNEWLINE_(label[off])) + break; + off += char_size; + } + + return off; +} + + +/****************************** + *** Recognizing raw HTML *** + ******************************/ + +/* md_is_html_tag() may be called when processing inlines (inline raw HTML) + * or when breaking document to blocks (checking for start of HTML block type 7). + * + * When breaking document to blocks, we do not yet know line boundaries, but + * in that case the whole tag has to live on a single line. We distinguish this + * by n_lines == 0. + */ +static int +md_is_html_tag(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + int attr_state; + OFF off = beg; + OFF line_end = (n_lines > 0) ? lines[0].end : ctx->size; + MD_SIZE line_index = 0; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 1 >= line_end) + return false; + off++; + + /* For parsing attributes, we need a little state automaton below. + * State -1: no attributes are allowed. + * State 0: attribute could follow after some whitespace. + * State 1: after a whitespace (attribute name may follow). + * State 2: after attribute name ('=' MAY follow). + * State 3: after '=' (value specification MUST follow). + * State 41: in middle of unquoted attribute value. + * State 42: in middle of single-quoted attribute value. + * State 43: in middle of double-quoted attribute value. + */ + attr_state = 0; + + if(CH(off) == _T('/')) { + /* Closer tag "". No attributes may be present. */ + attr_state = -1; + off++; + } + + /* Tag name */ + if(off >= line_end || !ISALPHA(off)) + return false; + off++; + while(off < line_end && (ISALNUM(off) || CH(off) == _T('-'))) + off++; + + /* (Optional) attributes (if not closer), (optional) '/' (if not closer) + * and final '>'. */ + while(1) { + while(off < line_end && !ISNEWLINE(off)) { + if(attr_state > 40) { + if(attr_state == 41 && (ISBLANK(off) || ISANYOF(off, _T("\"'=<>`")))) { + attr_state = 0; + off--; /* Put the char back for re-inspection in the new state. */ + } else if(attr_state == 42 && CH(off) == _T('\'')) { + attr_state = 0; + } else if(attr_state == 43 && CH(off) == _T('"')) { + attr_state = 0; + } + off++; + } else if(ISWHITESPACE(off)) { + if(attr_state == 0) + attr_state = 1; + off++; + } else if(attr_state <= 2 && CH(off) == _T('>')) { + /* End. */ + goto done; + } else if(attr_state <= 2 && CH(off) == _T('/') && off+1 < line_end && CH(off+1) == _T('>')) { + /* End with digraph '/>' */ + off++; + goto done; + } else if((attr_state == 1 || attr_state == 2) && (ISALPHA(off) || CH(off) == _T('_') || CH(off) == _T(':'))) { + off++; + /* Attribute name */ + while(off < line_end && (ISALNUM(off) || ISANYOF(off, _T("_.:-")))) + off++; + attr_state = 2; + } else if(attr_state == 2 && CH(off) == _T('=')) { + /* Attribute assignment sign */ + off++; + attr_state = 3; + } else if(attr_state == 3) { + /* Expecting start of attribute value. */ + if(CH(off) == _T('"')) + attr_state = 43; + else if(CH(off) == _T('\'')) + attr_state = 42; + else if(!ISANYOF(off, _T("\"'=<>`")) && !ISNEWLINE(off)) + attr_state = 41; + else + return false; + off++; + } else { + /* Anything unexpected. */ + return false; + } + } + + /* We have to be on a single line. See definition of start condition + * of HTML block, type 7. */ + if(n_lines == 0) + return false; + + line_index++; + if(line_index >= n_lines) + return false; + + off = lines[line_index].beg; + line_end = lines[line_index].end; + + if(attr_state == 0 || attr_state == 41) + attr_state = 1; + + if(off >= max_end) + return false; + } + +done: + if(off >= max_end) + return false; + + *p_end = off+1; + return true; +} + +static int +md_scan_for_html_closer(MD_CTX* ctx, const MD_CHAR* str, MD_SIZE len, + const MD_LINE* lines, MD_SIZE n_lines, + OFF beg, OFF max_end, OFF* p_end, + OFF* p_scan_horizon) +{ + OFF off = beg; + MD_SIZE line_index = 0; + + if(off < *p_scan_horizon && *p_scan_horizon >= max_end - len) { + /* We have already scanned the range up to the max_end so we know + * there is nothing to see. */ + return false; + } + + while(true) { + while(off + len <= lines[line_index].end && off + len <= max_end) { + if(md_ascii_eq(STR(off), str, len)) { + /* Success. */ + *p_end = off + len; + return true; + } + off++; + } + + line_index++; + if(off >= max_end || line_index >= n_lines) { + /* Failure. */ + *p_scan_horizon = off; + return false; + } + + off = lines[line_index].beg; + } +} + +static int +md_is_html_comment(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 4 >= lines[0].end) + return false; + if(CH(off+1) != _T('!') || CH(off+2) != _T('-') || CH(off+3) != _T('-')) + return false; + + /* Skip only "" or "" */ + off += 2; + + /* Scan for ordinary comment closer "-->". */ + return md_scan_for_html_closer(ctx, _T("-->"), 3, + lines, n_lines, off, max_end, p_end, &ctx->html_comment_horizon); +} + +static int +md_is_html_processing_instruction(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + + if(off + 2 >= lines[0].end) + return false; + if(CH(off+1) != _T('?')) + return false; + off += 2; + + return md_scan_for_html_closer(ctx, _T("?>"), 2, + lines, n_lines, off, max_end, p_end, &ctx->html_proc_instr_horizon); +} + +static int +md_is_html_declaration(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + + if(off + 2 >= lines[0].end) + return false; + if(CH(off+1) != _T('!')) + return false; + off += 2; + + /* Declaration name. */ + if(off >= lines[0].end || !ISALPHA(off)) + return false; + off++; + while(off < lines[0].end && ISALPHA(off)) + off++; + + return md_scan_for_html_closer(ctx, _T(">"), 1, + lines, n_lines, off, max_end, p_end, &ctx->html_decl_horizon); +} + +static int +md_is_html_cdata(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + static const CHAR open_str[] = _T("= lines[0].end) + return false; + if(memcmp(STR(off), open_str, open_size * sizeof(CHAR)) != 0) + return false; + off += open_size; + + return md_scan_for_html_closer(ctx, _T("]]>"), 3, + lines, n_lines, off, max_end, p_end, &ctx->html_cdata_horizon); +} + +static int +md_is_html_any(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + MD_ASSERT(CH(beg) == _T('<')); + return (md_is_html_tag(ctx, lines, n_lines, beg, max_end, p_end) || + md_is_html_comment(ctx, lines, n_lines, beg, max_end, p_end) || + md_is_html_processing_instruction(ctx, lines, n_lines, beg, max_end, p_end) || + md_is_html_declaration(ctx, lines, n_lines, beg, max_end, p_end) || + md_is_html_cdata(ctx, lines, n_lines, beg, max_end, p_end)); +} + + +/**************************** + *** Recognizing Entity *** + ****************************/ + +static int +md_is_hex_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + MD_UNUSED(ctx); + + while(off < max_end && ISXDIGIT_(text[off]) && off - beg <= 8) + off++; + + if(1 <= off - beg && off - beg <= 6) { + *p_end = off; + return true; + } else { + return false; + } +} + +static int +md_is_dec_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + MD_UNUSED(ctx); + + while(off < max_end && ISDIGIT_(text[off]) && off - beg <= 8) + off++; + + if(1 <= off - beg && off - beg <= 7) { + *p_end = off; + return true; + } else { + return false; + } +} + +static int +md_is_named_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + MD_UNUSED(ctx); + + if(off < max_end && ISALPHA_(text[off])) + off++; + else + return false; + + while(off < max_end && ISALNUM_(text[off]) && off - beg <= 48) + off++; + + if(2 <= off - beg && off - beg <= 48) { + *p_end = off; + return true; + } else { + return false; + } +} + +static int +md_is_entity_str(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + int is_contents; + OFF off = beg; + + MD_ASSERT(text[off] == _T('&')); + off++; + + if(off+2 < max_end && text[off] == _T('#') && (text[off+1] == _T('x') || text[off+1] == _T('X'))) + is_contents = md_is_hex_entity_contents(ctx, text, off+2, max_end, &off); + else if(off+1 < max_end && text[off] == _T('#')) + is_contents = md_is_dec_entity_contents(ctx, text, off+1, max_end, &off); + else + is_contents = md_is_named_entity_contents(ctx, text, off, max_end, &off); + + if(is_contents && off < max_end && text[off] == _T(';')) { + *p_end = off+1; + return true; + } else { + return false; + } +} + +static inline int +md_is_entity(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end) +{ + return md_is_entity_str(ctx, ctx->text, beg, max_end, p_end); +} + + +/****************************** + *** Attribute Management *** + ******************************/ + +typedef struct MD_ATTRIBUTE_BUILD_tag MD_ATTRIBUTE_BUILD; +struct MD_ATTRIBUTE_BUILD_tag { + CHAR* text; + MD_TEXTTYPE* substr_types; + OFF* substr_offsets; + SZ substr_count; + SZ substr_alloc; + MD_TEXTTYPE trivial_types[1]; + OFF trivial_offsets[2]; +}; + + +#define MD_BUILD_ATTR_NO_ESCAPES 0x0001 + +static int +md_build_attr_append_substr(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build, + MD_TEXTTYPE type, OFF off) +{ + if(build->substr_count >= build->substr_alloc) { + MD_TEXTTYPE* new_substr_types; + OFF* new_substr_offsets; + SZ new_alloc = (build->substr_alloc > 0 + ? build->substr_alloc + build->substr_alloc / 2 + : 8); + + new_substr_types = (MD_TEXTTYPE*) realloc(build->substr_types, + new_alloc * sizeof(MD_TEXTTYPE)); + if(new_substr_types == NULL) { + MD_LOG("realloc() failed."); + return -1; + } + build->substr_types = new_substr_types; + + /* Note +1 to reserve space for final offset (== raw_size). */ + new_substr_offsets = (OFF*) realloc(build->substr_offsets, + (new_alloc+1) * sizeof(OFF)); + if(new_substr_offsets == NULL) { + MD_LOG("realloc() failed."); + return -1; + } + build->substr_offsets = new_substr_offsets; + build->substr_alloc = new_alloc; + } + + build->substr_types[build->substr_count] = type; + build->substr_offsets[build->substr_count] = off; + build->substr_count++; + return 0; +} + +static void +md_free_attribute(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build) +{ + MD_UNUSED(ctx); + + /* A trivial build aliases caller-owned storage and must not be freed. + * Every other build owns all three pointers from the moment + * md_build_attribute() leaves the trivial branch, even if a growth + * realloc later failed while substr_alloc was still 0. Clearing them + * keeps this idempotent, which matters because md_build_attribute() + * frees on its own abort path before the caller frees again. */ + if(build->substr_types != build->trivial_types) { + free(build->text); + free(build->substr_types); + free(build->substr_offsets); + build->text = NULL; + build->substr_types = NULL; + build->substr_offsets = NULL; + build->substr_alloc = 0; + build->substr_count = 0; + } +} + +static int +md_build_attribute(MD_CTX* ctx, const CHAR* raw_text, SZ raw_size, + unsigned flags, MD_ATTRIBUTE* attr, MD_ATTRIBUTE_BUILD* build) +{ + OFF raw_off, off; + int is_trivial; + int ret = 0; + + memset(build, 0, sizeof(MD_ATTRIBUTE_BUILD)); + + /* If there is no backslash and no ampersand, build trivial attribute + * without any malloc(). */ + is_trivial = true; + for(raw_off = 0; raw_off < raw_size; raw_off++) { + if(ISANYOF3_(raw_text[raw_off], _T('\\'), _T('&'), _T('\0'))) { + is_trivial = false; + break; + } + } + + if(is_trivial) { + build->text = (CHAR*) (raw_size ? raw_text : NULL); + build->substr_types = build->trivial_types; + build->substr_offsets = build->trivial_offsets; + build->substr_count = 1; + build->substr_alloc = 0; + build->trivial_types[0] = MD_TEXT_NORMAL; + build->trivial_offsets[0] = 0; + build->trivial_offsets[1] = raw_size; + off = raw_size; + } else { + build->text = (CHAR*) malloc(raw_size * sizeof(CHAR)); + if(build->text == NULL) { + MD_LOG("malloc() failed."); + goto abort; + } + + raw_off = 0; + off = 0; + + while(raw_off < raw_size) { + if(raw_text[raw_off] == _T('\0')) { + MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_NULLCHAR, off)); + memcpy(build->text + off, raw_text + raw_off, sizeof(CHAR)); + off++; + raw_off++; + continue; + } + + if(raw_text[raw_off] == _T('&')) { + OFF ent_end; + + if(md_is_entity_str(ctx, raw_text, raw_off, raw_size, &ent_end)) { + MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_ENTITY, off)); + memcpy(build->text + off, raw_text + raw_off, (ent_end - raw_off) * sizeof(CHAR)); + off += ent_end - raw_off; + raw_off = ent_end; + continue; + } + } + + if(build->substr_count == 0 || build->substr_types[build->substr_count-1] != MD_TEXT_NORMAL) + MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_NORMAL, off)); + + if(!(flags & MD_BUILD_ATTR_NO_ESCAPES) && + raw_text[raw_off] == _T('\\') && raw_off+1 < raw_size && + (ISPUNCT_(raw_text[raw_off+1]) || ISNEWLINE_(raw_text[raw_off+1]))) + raw_off++; + + build->text[off++] = raw_text[raw_off++]; + } + build->substr_offsets[build->substr_count] = off; + } + + attr->text = build->text; + attr->size = off; + attr->substr_offsets = build->substr_offsets; + attr->substr_types = build->substr_types; + return 0; + +abort: + md_free_attribute(ctx, build); + return -1; +} + + +/************************************************** + *** Hashtable (with a text label as its key) *** + **************************************************/ + +#define MD_FNV1A_BASE 2166136261U +#define MD_FNV1A_PRIME 16777619U + +static inline unsigned +md_fnv1a(unsigned base, const void* data, size_t n) +{ + const unsigned char* buf = (const unsigned char*) data; + unsigned hash = base; + size_t i; + + for(i = 0; i < n; i++) { + hash ^= buf[i]; + hash *= MD_FNV1A_PRIME; + } + + return hash; +} + +/* Label equivalence is quite complicated with regards to whitespace and case + * folding. This complicates computing a hash of it as well as direct comparison + * of two labels. */ + +static unsigned +md_label_hash(const CHAR* label, SZ size) +{ + unsigned hash = MD_FNV1A_BASE; + OFF off; + unsigned codepoint; + int is_whitespace = false; + + off = md_skip_unicode_whitespace(label, 0, size); + while(off < size) { + SZ char_size; + + codepoint = md_decode_unicode(label, off, size, &char_size); + is_whitespace = ISUNICODEWHITESPACE_(codepoint) || ISNEWLINE_(label[off]); + + if(is_whitespace) { + codepoint = ' '; + hash = md_fnv1a(hash, &codepoint, sizeof(unsigned)); + off = md_skip_unicode_whitespace(label, off, size); + } else { + MD_UNICODE_FOLD_INFO fold_info; + + md_get_unicode_fold_info(codepoint, &fold_info); + hash = md_fnv1a(hash, fold_info.codepoints, fold_info.n_codepoints * sizeof(unsigned)); + off += char_size; + } + } + + return hash; +} + +static OFF +md_label_cmp_load_fold_info(const CHAR* label, OFF off, SZ size, + MD_UNICODE_FOLD_INFO* fold_info) +{ + unsigned codepoint; + SZ char_size; + + if(off >= size) { + /* Treat end of a link label as a whitespace. */ + goto whitespace; + } + + codepoint = md_decode_unicode(label, off, size, &char_size); + off += char_size; + if(ISUNICODEWHITESPACE_(codepoint)) { + /* Treat all whitespace as equivalent */ + goto whitespace; + } + + /* Get real folding info. */ + md_get_unicode_fold_info(codepoint, fold_info); + return off; + +whitespace: + fold_info->codepoints[0] = _T(' '); + fold_info->n_codepoints = 1; + return md_skip_unicode_whitespace(label, off, size); +} + +static int +md_label_cmp(const CHAR* a_label, SZ a_size, const CHAR* b_label, SZ b_size) +{ + OFF a_off; + OFF b_off; + MD_UNICODE_FOLD_INFO a_fi = { { 0 }, 0 }; + MD_UNICODE_FOLD_INFO b_fi = { { 0 }, 0 }; + OFF a_fi_off = 0; + OFF b_fi_off = 0; + int cmp; + + a_off = md_skip_unicode_whitespace(a_label, 0, a_size); + b_off = md_skip_unicode_whitespace(b_label, 0, b_size); + while(a_off < a_size || a_fi_off < a_fi.n_codepoints || + b_off < b_size || b_fi_off < b_fi.n_codepoints) + { + /* If needed, load fold info for next char. */ + if(a_fi_off >= a_fi.n_codepoints) { + a_fi_off = 0; + a_off = md_label_cmp_load_fold_info(a_label, a_off, a_size, &a_fi); + } + if(b_fi_off >= b_fi.n_codepoints) { + b_fi_off = 0; + b_off = md_label_cmp_load_fold_info(b_label, b_off, b_size, &b_fi); + } + + cmp = b_fi.codepoints[b_fi_off] - a_fi.codepoints[a_fi_off]; + if(cmp != 0) + return cmp; + + a_fi_off++; + b_fi_off++; + } + + return 0; +} + +typedef struct MD_LABEL_HASH_LIST_tag MD_LABEL_HASH_LIST; +struct MD_LABEL_HASH_LIST_tag { + unsigned n_entries; + unsigned alloc_entries; + MD_LABEL_HASH_ENTRY* entries[]; +}; + +static int +md_label_hash_entry_cmp(const void* a, const void* b) +{ + const MD_LABEL_HASH_ENTRY* a_entry = *(const MD_LABEL_HASH_ENTRY**)a; + const MD_LABEL_HASH_ENTRY* b_entry = *(const MD_LABEL_HASH_ENTRY**)b; + + if(a_entry->hash < b_entry->hash) + return -1; + else if(a_entry->hash > b_entry->hash) + return +1; + else + return md_label_cmp(a_entry->label, a_entry->label_size, + b_entry->label, b_entry->label_size); +} + +static int +md_label_hash_entry_cmp_for_sort(const void* a, const void* b) +{ + int cmp; + + cmp = md_label_hash_entry_cmp(a, b); + + /* Ensure stability of the sorting. */ + if(cmp == 0) { + const MD_LABEL_HASH_ENTRY* a_entry = *(const MD_LABEL_HASH_ENTRY**)a; + const MD_LABEL_HASH_ENTRY* b_entry = *(const MD_LABEL_HASH_ENTRY**)b; + + if(a_entry < b_entry) + cmp = -1; + else if(a_entry > b_entry) + cmp = +1; + } + + return cmp; +} + +static int +md_is_complex_label_bucket(MD_LABEL_HASH_TABLE* table, void* bucket) +{ + if(bucket == NULL) + return false; + + return (MD_LABEL_HASH_ENTRY*) bucket < (MD_LABEL_HASH_ENTRY*) table->defs || + (MD_LABEL_HASH_ENTRY*) bucket >= (MD_LABEL_HASH_ENTRY*)((char*)table->defs + table->n_defs * table->def_size); +} + +static int +md_build_label_hashtable(MD_CTX* ctx, MD_LABEL_HASH_TABLE* table) +{ + unsigned i, j; + + if(table->n_defs == 0) + return 0; + + table->n_buckets = (table->n_defs * 5) / 4; + table->buckets = malloc(table->n_buckets * sizeof(void*)); + if(table->buckets == NULL) { + MD_LOG("malloc() failed."); + goto abort; + } + memset(table->buckets, 0, table->n_buckets * sizeof(void*)); + + /* Each member of table->buckets[] can be: + * -- NULL, + * -- pointer to the MD_LABEL_HASH_ENTRY, or + * -- pointer to a MD_LABEL_HASH_LIST, which holds multiple pointers to + * such entries. + */ + for(i = 0; i < table->n_defs; i++) { + MD_LABEL_HASH_ENTRY* entry = (MD_LABEL_HASH_ENTRY*) ((char*) table->defs + i * table->def_size); + void** p_bucket = &table->buckets[entry->hash % table->n_buckets]; + MD_LABEL_HASH_LIST* list; + + if(*p_bucket == NULL) { + /* The bucket is empty. Make it just point to the entry. */ + *p_bucket = entry; + continue; + } + + if(!md_is_complex_label_bucket(table, *p_bucket)) + { + /* The bucket already contains one entry. Lets see whether it is the + * same label (duplicate) or different one (hash conflict). */ + MD_LABEL_HASH_ENTRY* old_entry = (MD_LABEL_HASH_ENTRY*) *p_bucket; + + if(md_label_cmp(entry->label, entry->label_size, + old_entry->label, old_entry->label_size) == 0) { + /* Duplicate label: We may ignore this definition. */ + continue; + } + + /* Make the bucket complex, i.e. able to hold more entries. */ + list = (MD_LABEL_HASH_LIST*) malloc(sizeof(MD_LABEL_HASH_LIST) + + 2 * sizeof(MD_LABEL_HASH_ENTRY*)); + if(list == NULL) { + MD_LOG("malloc() failed."); + goto abort; + } + list->entries[0] = old_entry; + list->entries[1] = entry; + list->n_entries = 2; + list->alloc_entries = 2; + *p_bucket = list; + continue; + } + + /* Append the entry to the complex bucket list. + * + * Note in this case we ignore potential duplicates to avoid expensive + * iterating over the complex bucket. Below, we revisit all the complex + * buckets and handle it more cheaply after the complex bucket contents + * is sorted. */ + list = (MD_LABEL_HASH_LIST*) *p_bucket; + if(list->n_entries >= list->alloc_entries) { + size_t alloc_entries = list->alloc_entries + list->alloc_entries / 2; + MD_LABEL_HASH_LIST* list_tmp = (MD_LABEL_HASH_LIST*) realloc(list, + sizeof(MD_LABEL_HASH_LIST) + alloc_entries * sizeof(MD_LABEL_HASH_ENTRY*)); + if(list_tmp == NULL) { + MD_LOG("realloc() failed."); + goto abort; + } + list = list_tmp; + list->alloc_entries = (unsigned) alloc_entries; + table->buckets[entry->hash % table->n_buckets] = list; + } + + list->entries[list->n_entries] = entry; + list->n_entries++; + } + + /* Sort the complex buckets so we can use bsearch() with them. */ + for(i = 0; i < table->n_buckets; i++) { + void* bucket = table->buckets[i]; + MD_LABEL_HASH_LIST* list; + + if(bucket == NULL) + continue; + + if(!md_is_complex_label_bucket(table, bucket)) + continue; + + list = (MD_LABEL_HASH_LIST*) bucket; + qsort(list->entries, list->n_entries, sizeof(MD_LABEL_HASH_ENTRY*), + md_label_hash_entry_cmp_for_sort); + + /* Disable all duplicates in the complex bucket by forcing all such + * records to point to the 1st such entry. I.e. no matter which + * record is found during the lookup, it will always point to the right + * definition. */ + for(j = 1; j < list->n_entries; j++) { + if(md_label_hash_entry_cmp(&list->entries[j-1], &list->entries[j]) == 0) + list->entries[j] = list->entries[j-1]; + } + } + + return 0; + +abort: + return -1; +} + +static void +md_free_label_hashtable(MD_CTX* ctx, MD_LABEL_HASH_TABLE* table) +{ + MD_UNUSED(ctx); + + if(table->buckets != NULL) { + unsigned i; + + for(i = 0; i < table->n_buckets; i++) { + void* bucket = table->buckets[i]; + if(md_is_complex_label_bucket(table, bucket)) + free(bucket); + } + + free(table->buckets); + } +} + +static const MD_LABEL_HASH_ENTRY* +md_lookup_label_hashtable(MD_CTX* ctx, MD_LABEL_HASH_TABLE* table, const CHAR* label, SZ label_size) +{ + unsigned hash; + void* bucket; + + MD_UNUSED(ctx); + + if(table->n_buckets == 0) + return NULL; + + hash = md_label_hash(label, label_size); + bucket = table->buckets[hash % table->n_buckets]; + + if(bucket == NULL) { + return NULL; + } else if(!md_is_complex_label_bucket(table, bucket)) { + MD_LABEL_HASH_ENTRY* entry = (MD_LABEL_HASH_ENTRY*) bucket; + + if(entry->hash == hash && + md_label_cmp(entry->label, entry->label_size, label, label_size) == 0) + return entry; + else + return NULL; + } else { + MD_LABEL_HASH_LIST* list = (MD_LABEL_HASH_LIST*) bucket; + MD_LABEL_HASH_ENTRY key_buf; + const MD_LABEL_HASH_ENTRY* key = &key_buf; + MD_LABEL_HASH_ENTRY** ret; + + key_buf.label = (CHAR*) label; + key_buf.label_size = label_size; + key_buf.hash = hash; + + ret = (MD_LABEL_HASH_ENTRY**) bsearch(&key, list->entries, + list->n_entries, sizeof(MD_LABEL_HASH_ENTRY*), md_label_hash_entry_cmp); + if(ret != NULL) + return *ret; + else + return NULL; + } +} + +static void* +md_add_label_def(MD_CTX* ctx, MD_LABEL_HASH_TABLE* table, const CHAR* label, SZ label_size) +{ + MD_LABEL_HASH_ENTRY* entry; + + if(table->n_defs >= table->alloc_defs) { + size_t new_alloc_defs; + void* new_defs; + + new_alloc_defs = (table->alloc_defs > 0 + ? table->alloc_defs + table->alloc_defs / 2 + : 8); + new_defs = realloc(table->defs, new_alloc_defs * table->def_size); + if(new_defs == NULL) { + MD_LOG("realloc() failed."); + return NULL; + } + + table->defs = new_defs; + table->alloc_defs = (unsigned) new_alloc_defs; + } + + entry = (MD_LABEL_HASH_ENTRY*)((char*)table->defs + table->n_defs * table->def_size); + memset(entry, 0, table->def_size); + entry->label = label; + entry->label_size = label_size; + entry->hash = md_label_hash(label, label_size); + + table->n_defs++; + + return entry; +} + + +/************************************ + *** Link Reference Definitions *** + ************************************/ + +struct MD_REF_DEF_tag { + MD_LABEL_HASH_ENTRY entry; + CHAR* title; + SZ title_size; + OFF dest_beg; + OFF dest_end; + unsigned char label_needs_free : 1; + unsigned char title_needs_free : 1; +}; + +static int +md_build_ref_def_hashtable(MD_CTX* ctx) +{ + return md_build_label_hashtable(ctx, &ctx->ref_def_hashtable); +} + +static const MD_REF_DEF* +md_lookup_ref_def(MD_CTX* ctx, const CHAR* label, SZ label_size) +{ + return (const MD_REF_DEF*) md_lookup_label_hashtable(ctx, + &ctx->ref_def_hashtable, label, label_size); +} + + +/******************************* + *** Footnote Definitions *** + *******************************/ + +struct MD_FOOTNOTE_DEF_tag { + MD_LABEL_HASH_ENTRY entry; + unsigned int index; /* 0 = unreferenced; 1-based order of first reference */ + unsigned int ref_count; /* Number of references to this footnote. */ + MD_LINE* content_lines; /* always heap-allocated; freed by md_free_footnote_defs */ + MD_SIZE n_content_lines; +}; + +static int +md_is_footnote_label(MD_CTX* ctx, OFF beg, OFF* p_end) +{ + OFF end = beg; + + /* No whitespace, no nested square brackets and length below 75 characters. + * See https://github.com/mity/md4c/issues/380 */ + while(end < ctx->size && end - beg <= 75 && + !ISWHITESPACE(end) && !ISANYOF2(end, _T('['), _T(']'))) + end++; + + if(end - beg > 0 && end < ctx->size && CH(end) == _T(']')) { + if(p_end != NULL) + *p_end = end; + return true; + } else { + return false; + } +} + +/* Returns 0 if not a footnote definition. + * Returns N > 0 (number of lines consumed) if it is one and the definition + * was stored successfully. + * Returns -1 on memory allocation error. + */ +static int +md_is_footnote_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) +{ + OFF off; + OFF label_beg, label_end; + MD_LINE* content_lines = NULL; + MD_FOOTNOTE_DEF* def; + MD_SIZE n; + MD_SIZE n_content_lines; + int ret = 0; + + /* Caller guarantees: n_lines >= 1 and lines[0] starts with [^. */ + MD_ASSERT(n_lines >= 1); + off = lines[0].beg; + MD_ASSERT(CH(off) == _T('[') && CH(off+1) == _T('^')); + off += 2; + + label_beg = off; + if(!md_is_footnote_label(ctx, label_beg, &off)) + return false; + label_end = off; + + /* Closing bracket. */ + if(off >= lines[0].end || CH(off) != _T(']')) + return false; + off++; + + /* Colon. */ + if(off >= lines[0].end || CH(off) != _T(':')) + return false; + off++; + + /* Skip optional whitespace after colon on the first line. */ + while(off < lines[0].end && ISWHITESPACE(off)) + off++; + + /* Count continuation lines. GitHub-style footnotes allow the rest of the + * paragraph block to form the footnote body, including unindented lines. + * + * Blank lines cannot appear inside a paragraph block (they always trigger + * a block boundary), so we do not need to handle them here. Stop before a + * following line which itself starts a new footnote definition. */ + n = 1; + while(n < n_lines) { + OFF def_off = lines[n].beg; + + if(def_off + 3 < lines[n].end && CH(def_off) == _T('[') && CH(def_off+1) == _T('^')) { + OFF tmp = def_off + 2; + + while(tmp < lines[n].end && CH(tmp) != _T(']') && + !ISWHITESPACE(tmp) && CH(tmp) != _T('[')) + tmp++; + + if(tmp > def_off + 2 && tmp + 1 < lines[n].end && + CH(tmp) == _T(']') && CH(tmp+1) == _T(':')) + break; + } + + n++; + } + + /* Build content_lines array. + * Line 0 content starts after the "[^label]: " prefix. + * Lines 1..n-1 are stored verbatim (md4c strips indentation before + * handing us MD_LINE, so no further adjustment is needed). */ + n_content_lines = (off >= lines[0].end && n > 1) ? n - 1 : n; + content_lines = (MD_LINE*) malloc(n_content_lines * sizeof(MD_LINE)); + if(content_lines == NULL) { + MD_LOG("malloc() failed."); + ret = -1; + goto abort; + } + + if(n_content_lines < n) { + memcpy(content_lines, lines + 1, n_content_lines * sizeof(MD_LINE)); + } else { + content_lines[0].beg = off; + content_lines[0].end = lines[0].end; + if(n > 1) + memcpy(content_lines + 1, lines + 1, (n - 1) * sizeof(MD_LINE)); + } + + def = (MD_FOOTNOTE_DEF*) md_add_label_def(ctx, &ctx->footnote_hashtable, + (CHAR*) STR(label_beg), label_end - label_beg); + if(def == NULL) { + ret = -1; + goto abort; + } + def->content_lines = content_lines; + def->n_content_lines = n_content_lines; + + return (int) n; + +abort: + free(content_lines); + return ret; +} + +static MD_FOOTNOTE_DEF* +md_lookup_footnote_def(MD_CTX* ctx, const CHAR* label, SZ label_size) +{ + return (MD_FOOTNOTE_DEF*) md_lookup_label_hashtable(ctx, + &ctx->footnote_hashtable, label, label_size); +} + +static int +md_build_footnote_def_hashtable(MD_CTX* ctx) +{ + return md_build_label_hashtable(ctx, &ctx->footnote_hashtable); +} + +static void +md_free_footnote_defs(MD_CTX* ctx) +{ + unsigned i; + + md_free_label_hashtable(ctx, &ctx->footnote_hashtable); + + for(i = 0; i < ctx->footnote_hashtable.n_defs; i++) + free(ctx->footnote_hashtable.footnote_defs[i].content_lines); + free(ctx->footnote_hashtable.footnote_defs); +} + + +/*************************** + *** Recognizing Links *** + ***************************/ + +/* Note this code is partially shared between processing inlines and blocks + * as reference definitions and links share some helper parser functions. + */ + +typedef struct MD_LINK_ATTR_tag MD_LINK_ATTR; +struct MD_LINK_ATTR_tag { + OFF dest_beg; + OFF dest_end; + + CHAR* title; + SZ title_size; + int title_needs_free; +}; + + +static int +md_is_link_label(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, + OFF* p_end, MD_SIZE* p_beg_line_index, MD_SIZE* p_end_line_index, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + OFF contents_beg = 0; + OFF contents_end = 0; + MD_SIZE line_index = 0; + int len = 0; + + *p_beg_line_index = 0; + + if(CH(off) != _T('[')) + return false; + off++; + + while(1) { + OFF line_end = lines[line_index].end; + + while(off < line_end) { + if(CH(off) == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) { + if(contents_end == 0) { + contents_beg = off; + *p_beg_line_index = line_index; + } + contents_end = off + 2; + off += 2; + } else if(CH(off) == _T('[')) { + return false; + } else if(CH(off) == _T(']')) { + if(contents_beg < contents_end) { + /* Success. */ + *p_contents_beg = contents_beg; + *p_contents_end = contents_end; + *p_end = off+1; + *p_end_line_index = line_index; + return true; + } else { + /* Link label must have some non-whitespace contents. */ + return false; + } + } else { + unsigned codepoint; + SZ char_size; + + codepoint = md_decode_unicode(ctx->text, off, ctx->size, &char_size); + if(!ISUNICODEWHITESPACE_(codepoint)) { + if(contents_end == 0) { + contents_beg = off; + *p_beg_line_index = line_index; + } + contents_end = off + char_size; + } + + off += char_size; + } + + len++; + if(len > 999) + return false; + } + + line_index++; + len++; + if(line_index < n_lines) + off = lines[line_index].beg; + else + break; + } + + return false; +} + +static int +md_is_link_destination_A(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + + if(off >= max_end || CH(off) != _T('<')) + return false; + off++; + + while(off < max_end) { + if(CH(off) == _T('\\') && off+1 < max_end && ISPUNCT(off+1)) { + off += 2; + continue; + } + + if(ISNEWLINE(off) || CH(off) == _T('<')) + return false; + + if(CH(off) == _T('>')) { + /* Success. */ + *p_contents_beg = beg+1; + *p_contents_end = off; + *p_end = off+1; + return true; + } + + off++; + } + + return false; +} + +static int +md_is_link_destination_B(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + int parenthesis_level = 0; + + while(off < max_end) { + if(CH(off) == _T('\\') && off+1 < max_end && ISPUNCT(off+1)) { + off += 2; + continue; + } + + if(ISWHITESPACE(off) || ISCNTRL(off)) + break; + + /* Link destination may include balanced pairs of unescaped '(' ')'. + * Note we limit the maximal nesting level by 32 to protect us from + * https://github.com/jgm/cmark/issues/214 */ + if(CH(off) == _T('(')) { + parenthesis_level++; + if(parenthesis_level > 32) + return false; + } else if(CH(off) == _T(')')) { + if(parenthesis_level == 0) + break; + parenthesis_level--; + } + + off++; + } + + if(parenthesis_level != 0 || off == beg) + return false; + + /* Success. */ + *p_contents_beg = beg; + *p_contents_end = off; + *p_end = off; + return true; +} + +static inline int +md_is_link_destination(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, + OFF* p_contents_beg, OFF* p_contents_end) +{ + if(CH(beg) == _T('<')) + return md_is_link_destination_A(ctx, beg, max_end, p_end, p_contents_beg, p_contents_end); + else + return md_is_link_destination_B(ctx, beg, max_end, p_end, p_contents_beg, p_contents_end); +} + +static int +md_is_link_title(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, + OFF* p_end, MD_SIZE* p_beg_line_index, MD_SIZE* p_end_line_index, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + CHAR closer_char; + MD_SIZE line_index = 0; + + /* White space with up to one line break. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end) { + line_index++; + if(line_index >= n_lines) + return false; + off = lines[line_index].beg; + } + if(off == beg) + return false; + + *p_beg_line_index = line_index; + + /* First char determines how to detect end of it. */ + switch(CH(off)) { + case _T('"'): closer_char = _T('"'); break; + case _T('\''): closer_char = _T('\''); break; + case _T('('): closer_char = _T(')'); break; + default: return false; + } + off++; + + *p_contents_beg = off; + + while(line_index < n_lines) { + OFF line_end = lines[line_index].end; + + while(off < line_end) { + if(CH(off) == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) { + off++; + } else if(CH(off) == closer_char) { + /* Success. */ + *p_contents_end = off; + *p_end = off+1; + *p_end_line_index = line_index; + return true; + } else if(closer_char == _T(')') && CH(off) == _T('(')) { + /* ()-style title cannot contain (unescaped '(')) */ + return false; + } + + off++; + } + + line_index++; + } + + return false; +} + +/* Returns 0 if it is not a reference definition. + * + * Returns N > 0 if it is a reference definition. N then corresponds to the + * number of lines forming it). In this case the definition is stored for + * resolving any links referring to it. + * + * Returns -1 in case of an error (out of memory). + */ +static int +md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) +{ + OFF label_contents_beg; + OFF label_contents_end; + MD_SIZE label_contents_line_index; + int label_is_multiline = false; + OFF dest_contents_beg; + OFF dest_contents_end; + OFF title_contents_beg; + OFF title_contents_end; + MD_SIZE title_contents_line_index; + int title_is_multiline = false; + OFF off; + MD_SIZE line_index = 0; + MD_SIZE tmp_line_index; + MD_REF_DEF* def = NULL; + int ret = 0; + + /* Link label. */ + if(!md_is_link_label(ctx, lines, n_lines, lines[0].beg, + &off, &label_contents_line_index, &line_index, + &label_contents_beg, &label_contents_end)) + return false; + label_is_multiline = (label_contents_line_index != line_index); + + /* Colon. */ + if(off >= lines[line_index].end || CH(off) != _T(':')) + return false; + off++; + + /* Optional white space with up to one line break. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end) { + line_index++; + if(line_index >= n_lines) + return false; + off = lines[line_index].beg; + } + + /* Link destination. */ + if(!md_is_link_destination(ctx, off, lines[line_index].end, + &off, &dest_contents_beg, &dest_contents_end)) + return false; + + /* (Optional) title. Note we interpret it as an title only if nothing + * more follows on its last line. */ + if(md_is_link_title(ctx, lines + line_index, n_lines - line_index, off, + &off, &title_contents_line_index, &tmp_line_index, + &title_contents_beg, &title_contents_end) + && off >= lines[line_index + tmp_line_index].end) + { + title_is_multiline = (tmp_line_index != title_contents_line_index); + title_contents_line_index += line_index; + line_index += tmp_line_index; + } else { + /* Not a title. */ + title_is_multiline = false; + title_contents_beg = off; + title_contents_end = off; + title_contents_line_index = 0; + } + + /* Nothing more can follow on the last line. */ + if(off < lines[line_index].end) + return false; + + if(label_is_multiline) { + CHAR* label; + SZ label_size; + + MD_CHECK(md_merge_lines_alloc(ctx, label_contents_beg, label_contents_end, + lines + label_contents_line_index, n_lines - label_contents_line_index, + _T(' '), &label, &label_size)); + def = (MD_REF_DEF*) md_add_label_def(ctx, &ctx->ref_def_hashtable, label, label_size); + if(def == NULL) { + ret = -1; + free(label); + goto abort; + } + def->label_needs_free = true; + } else { + def = (MD_REF_DEF*) md_add_label_def(ctx, &ctx->ref_def_hashtable, + STR(label_contents_beg), label_contents_end - label_contents_beg); + if(def == NULL) { + ret = -1; + goto abort; + } + } + + if(title_is_multiline) { + MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end, + lines + title_contents_line_index, n_lines - title_contents_line_index, + _T('\n'), &def->title, &def->title_size)); + def->title_needs_free = true; + } else { + def->title = (CHAR*) STR(title_contents_beg); + def->title_size = title_contents_end - title_contents_beg; + } + + def->dest_beg = dest_contents_beg; + def->dest_end = dest_contents_end; + + /* Success. */ + return line_index + 1; + +abort: + /* Failure. A non-NULL def is already committed to ctx->ref_def_hashtable, + * which owns its label and title and frees them in md_free_ref_defs(). + * The def == NULL path frees its local label itself, above. */ + return ret; +} + +static int +md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, + OFF beg, OFF end, MD_LINK_ATTR* attr) +{ + const MD_REF_DEF* def; + const MD_LINE* beg_line; + int is_multiline; + CHAR* label; + SZ label_size; + int ret = false; + + MD_ASSERT(CH(beg) == _T('[') || CH(beg) == _T('!')); + MD_ASSERT(CH(end-1) == _T(']')); + + if(ctx->max_ref_def_output == 0) + return false; + + beg += (CH(beg) == _T('!') ? 2 : 1); + end--; + + /* Find lines corresponding to the beg and end positions. */ + beg_line = md_lookup_line(beg, lines, n_lines, NULL); + is_multiline = (end > beg_line->end); + + if(is_multiline) { + MD_CHECK(md_merge_lines_alloc(ctx, beg, end, beg_line, + (int)(n_lines - (beg_line - lines)), _T(' '), &label, &label_size)); + } else { + label = (CHAR*) STR(beg); + label_size = end - beg; + } + + def = md_lookup_ref_def(ctx, label, label_size); + if(def != NULL) { + attr->dest_beg = def->dest_beg; + attr->dest_end = def->dest_end; + attr->title = def->title; + attr->title_size = def->title_size; + attr->title_needs_free = false; + } + + if(is_multiline) + free(label); + + if(def != NULL) { + /* See https://github.com/mity/md4c/issues/238 */ + MD_SIZE output_size_estimation = def->entry.label_size + def->title_size + def->dest_end - def->dest_beg; + if(output_size_estimation < ctx->max_ref_def_output) { + ctx->max_ref_def_output -= output_size_estimation; + ret = true; + } else { + MD_LOG("Too many link reference definition instantiations."); + ctx->max_ref_def_output = 0; + } + } + +abort: + return ret; +} + +static int +md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, + OFF beg, OFF* p_end, MD_LINK_ATTR* attr) +{ + MD_SIZE line_index = 0; + MD_SIZE tmp_line_index; + OFF title_contents_beg; + OFF title_contents_end; + MD_SIZE title_contents_line_index; + int title_is_multiline; + OFF off = beg; + int ret = false; + + md_lookup_line(off, lines, n_lines, &line_index); + + MD_ASSERT(CH(off) == _T('(')); + off++; + + /* Optional white space with up to one line break. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end && (off >= ctx->size || ISNEWLINE(off))) { + line_index++; + if(line_index >= n_lines) + return false; + off = lines[line_index].beg; + } + + /* Link destination may be omitted, but only when not also having a title. */ + if(off < ctx->size && CH(off) == _T(')')) { + attr->dest_beg = off; + attr->dest_end = off; + attr->title = NULL; + attr->title_size = 0; + attr->title_needs_free = false; + off++; + *p_end = off; + return true; + } + + /* Link destination. */ + if(!md_is_link_destination(ctx, off, lines[line_index].end, + &off, &attr->dest_beg, &attr->dest_end)) + return false; + + /* (Optional) title. */ + if(md_is_link_title(ctx, lines + line_index, n_lines - line_index, off, + &off, &title_contents_line_index, &tmp_line_index, + &title_contents_beg, &title_contents_end)) + { + title_is_multiline = (tmp_line_index != title_contents_line_index); + title_contents_line_index += line_index; + line_index += tmp_line_index; + } else { + /* Not a title. */ + title_is_multiline = false; + title_contents_beg = off; + title_contents_end = off; + title_contents_line_index = 0; + } + + /* Optional whitespace followed with final ')'. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end) { + line_index++; + if(line_index >= n_lines) + return false; + off = lines[line_index].beg; + } + if(CH(off) != _T(')')) + goto abort; + off++; + + if(title_contents_beg >= title_contents_end) { + attr->title = NULL; + attr->title_size = 0; + attr->title_needs_free = false; + } else if(!title_is_multiline) { + attr->title = (CHAR*) STR(title_contents_beg); + attr->title_size = title_contents_end - title_contents_beg; + attr->title_needs_free = false; + } else { + MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end, + lines + title_contents_line_index, n_lines - title_contents_line_index, + _T('\n'), &attr->title, &attr->title_size)); + attr->title_needs_free = true; + } + + *p_end = off; + ret = true; + +abort: + return ret; +} + +static void +md_free_ref_defs(MD_CTX* ctx) +{ + unsigned i; + + md_free_label_hashtable(ctx, &ctx->ref_def_hashtable); + + for(i = 0; i < ctx->ref_def_hashtable.n_defs; i++) { + MD_REF_DEF* def = &ctx->ref_def_hashtable.ref_defs[i]; + + if(def->label_needs_free) + free((void*) def->entry.label); + if(def->title_needs_free) + free(def->title); + } + + free(ctx->ref_def_hashtable.ref_defs); +} + + +/****************************************** + *** Processing Inlines (a.k.a Spans) *** + ******************************************/ + +/* We process inlines in few phases: + * + * (1) We go through the block text and collect all significant characters + * which may start/end a span or some other significant position into + * ctx->marks[]. Core of this is what md_collect_marks() does. + * + * We also do some very brief preliminary context-less analysis, whether + * it might be opener or closer (e.g. of an emphasis span). + * + * This speeds the other steps as we do not need to re-iterate over all + * characters anymore. + * + * (2) We analyze each potential mark types, in order by their precedence. + * + * In each md_analyze_XXX() function, we re-iterate list of the marks, + * skipping already resolved regions (in preceding precedences) and try to + * resolve them. + * + * (2.1) For trivial marks, which are single (e.g. HTML entity), we just mark + * them as resolved. + * + * (2.2) For range-type marks, we analyze whether the mark could be closer + * and, if yes, whether there is some preceding opener it could satisfy. + * + * If not we check whether it could be really an opener and if yes, we + * remember it so subsequent closers may resolve it. + * + * (3) Finally, when all marks were analyzed, we render the block contents + * by calling MD_RENDERER::text() callback, interrupting by ::enter_span() + * or ::close_span() whenever we reach a resolved mark. + */ + + +/* The mark structure. + * + * '\\': Maybe escape sequence. + * '\0': NULL char. + * '*': Maybe (strong) emphasis start/end. + * '_': Maybe (strong) emphasis start/end. + * '~': Maybe strikethrough start/end (needs MD_FLAG_STRIKETHROUGH). + * '+': Maybe insert start/end (needs MD_FLAG_INSERT) + * '`': Maybe code span start/end. + * '&': Maybe start of entity. + * ';': Maybe end of entity. + * '<': Maybe start of raw HTML or autolink. + * '>': Maybe end of raw HTML or autolink. + * '=': Maybe highlight start/end (needs MD_FLAG_HIGHLIGHT). + * '[': Maybe start of link label or link text. + * '!': Equivalent of '[' for image. + * ']': Maybe end of link label or link text. + * '@': Maybe permissive e-mail auto-link (needs MD_FLAG_PERMISSIVEEMAILAUTOLINKS). + * ':': Maybe permissive URL auto-link (needs MD_FLAG_PERMISSIVEURLAUTOLINKS). + * '.': Maybe permissive WWW auto-link (needs MD_FLAG_PERMISSIVEWWWAUTOLINKS). + * 'D': Dummy mark, it reserves a space for splitting a previous mark + * (e.g. emphasis) or to make more space for storing some special data + * related to the preceding mark (e.g. link). + * + * Note that not all instances of these chars in the text imply creation of the + * structure. Only those which have (or may have, after we see more context) + * the special meaning. + * + * (Keep this struct as small as possible to fit as much of them into CPU + * cache line.) + */ +struct MD_MARK_tag { + union { + struct { + OFF beg; + OFF end; + }; + void* pointer; /* Dummy marks can sometimes store a pointer */ + }; + + /* For unresolved openers, 'next' may be used to form a stack of + * unresolved open openers. + * + * When resolved with MD_MARK_OPENER/CLOSER flag, next/prev is index of the + * respective closer/opener. + */ + int prev; + int next; + CHAR ch; + unsigned char flags; +}; + +/* Mark flags (these apply to ALL mark types). */ +#define MD_MARK_POTENTIAL_OPENER 0x01 /* Maybe opener. */ +#define MD_MARK_POTENTIAL_CLOSER 0x02 /* Maybe closer. */ +#define MD_MARK_OPENER 0x04 /* Definitely opener. */ +#define MD_MARK_CLOSER 0x08 /* Definitely closer. */ +#define MD_MARK_RESOLVED 0x10 /* Resolved in any definite way. */ + +/* Mark flags specific for just some mark type(s) (so the bits can be reused). */ +#define MD_MARK_EMPH_OC 0x20 /* Opener/closer mixed candidate. Helper for the "rule of 3". */ +#define MD_MARK_EMPH_MOD3_0 0x40 +#define MD_MARK_EMPH_MOD3_1 0x80 +#define MD_MARK_EMPH_MOD3_2 (0x40 | 0x80) +#define MD_MARK_EMPH_MOD3_MASK (0x40 | 0x80) +#define MD_MARK_AUTOLINK 0x20 /* Distinguisher for '<', '>'. */ +#define MD_MARK_AUTOLINK_MISSING_MAILTO 0x40 /* For '@' */ +#define MD_MARK_VALIDPERMISSIVEAUTOLINK 0x20 /* For '@', ':', '.'. */ +#define MD_MARK_BRACKET_CANBEIMAGE 0x20 /* For '[', if can be expanded to the left to eat '!'. */ +#define MD_MARK_BRACKET_HASNESTED 0x40 /* For '[' to rule out invalid link labels early. */ +#define MD_MARK_BRACKET_FOOTNOTEREF 0x80 /* For '[', To distinguish footnotes. */ + +static MD_MARKSTACK* +md_emph_stack(MD_CTX* ctx, MD_CHAR ch, unsigned flags) +{ + MD_MARKSTACK* stack; + + switch(ch) { + case '*': stack = &ASTERISK_OPENERS_oo_mod3_0; break; + case '_': stack = &UNDERSCORE_OPENERS_oo_mod3_0; break; + default: MD_UNREACHABLE(); + } + + if(flags & MD_MARK_EMPH_OC) + stack += 3; + + switch(flags & MD_MARK_EMPH_MOD3_MASK) { + case MD_MARK_EMPH_MOD3_0: stack += 0; break; + case MD_MARK_EMPH_MOD3_1: stack += 1; break; + case MD_MARK_EMPH_MOD3_2: stack += 2; break; + default: MD_UNREACHABLE(); + } + + return stack; +} + +static MD_MARKSTACK* +md_opener_stack(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + switch(mark->ch) { + case _T('*'): + case _T('_'): return md_emph_stack(ctx, mark->ch, mark->flags); + + case _T('~'): return (mark->end - mark->beg == 1) ? &TILDE_OPENERS_1 : &TILDE_OPENERS_2; + + case _T('!'): + case _T('['): return &BRACKET_OPENERS; + + default: MD_UNREACHABLE(); + } +} + +static MD_MARK* +md_add_mark(MD_CTX* ctx) +{ + if(ctx->n_marks >= ctx->alloc_marks) { + MD_MARK* new_marks; + + ctx->alloc_marks = (ctx->alloc_marks > 0 + ? ctx->alloc_marks + ctx->alloc_marks / 2 + : 64); + new_marks = realloc(ctx->marks, ctx->alloc_marks * sizeof(MD_MARK)); + if(new_marks == NULL) { + MD_LOG("realloc() failed."); + return NULL; + } + + ctx->marks = new_marks; + } + + return &ctx->marks[ctx->n_marks++]; +} + +#define ADD_MARK_() \ + do { \ + mark = md_add_mark(ctx); \ + if(mark == NULL) { \ + ret = -1; \ + goto abort; \ + } \ + } while(0) + +#define ADD_MARK(ch_, beg_, end_, flags_) \ + do { \ + ADD_MARK_(); \ + mark->beg = (beg_); \ + mark->end = (end_); \ + mark->prev = -1; \ + mark->next = -1; \ + mark->ch = (char)(ch_); \ + mark->flags = (flags_); \ + } while(0) + + +static inline void +md_mark_stack_push(MD_CTX* ctx, MD_MARKSTACK* stack, int mark_index) +{ + ctx->marks[mark_index].next = stack->top; + stack->top = mark_index; +} + +static inline int +md_mark_stack_pop(MD_CTX* ctx, MD_MARKSTACK* stack) +{ + int top = stack->top; + if(top >= 0) + stack->top = ctx->marks[top].next; + return top; +} + +/* Sometimes, we need to store a pointer into the mark. It can only happen + * for dummy marks. */ +static inline void +md_mark_store_ptr(MD_CTX* ctx, int mark_index, void* ptr) +{ + MD_ASSERT(ctx->marks[mark_index].ch == 'D'); + ctx->marks[mark_index].pointer = ptr; +} + +static inline void* +md_mark_get_ptr(MD_CTX* ctx, int mark_index) +{ + MD_ASSERT(ctx->marks[mark_index].ch == 'D'); + return ctx->marks[mark_index].pointer; +} + +static inline void +md_resolve_range(MD_CTX* ctx, int opener_index, int closer_index) +{ + MD_MARK* opener = &ctx->marks[opener_index]; + MD_MARK* closer = &ctx->marks[closer_index]; + + /* Interconnect opener and closer and mark both as resolved. */ + opener->next = closer_index; + closer->prev = opener_index; + + opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED; + closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED; +} + +/* Pop all opener records in the activated chains after the given mark. + * This makes sure, we have no crossing ranges. */ +static void +md_pop_openers(MD_CTX* ctx, int opener_index) +{ + int i; + + for(i = 0; i < (int) SIZEOF_ARRAY(ctx->opener_stacks); i++) { + MD_MARKSTACK* stack = &ctx->opener_stacks[i]; + while(stack->top >= opener_index) + md_mark_stack_pop(ctx, stack); + } +} + +static void +md_disable_marks(MD_CTX* ctx, int mark_index0, int mark_index1) +{ + int i; + + for(i = mark_index0; i < mark_index1; i++) { + MD_MARK* mark = &ctx->marks[i]; + + mark->ch = 'D'; + mark->flags = 0; + } +} + +static void +md_build_mark_char_map(MD_CTX* ctx) +{ + memset(ctx->mark_char_map, 0, sizeof(ctx->mark_char_map)); + + ctx->mark_char_map['\\'] = 1; + ctx->mark_char_map['*'] = 1; + ctx->mark_char_map['_'] = 1; + ctx->mark_char_map['`'] = 1; + ctx->mark_char_map['&'] = 1; + ctx->mark_char_map[';'] = 1; + ctx->mark_char_map['<'] = 1; + ctx->mark_char_map['>'] = 1; + ctx->mark_char_map['['] = 1; + ctx->mark_char_map['!'] = 1; + ctx->mark_char_map[']'] = 1; + ctx->mark_char_map['\0'] = 1; + + if(ctx->parser.flags & (MD_FLAG_STRIKETHROUGH | MD_FLAG_SUBSCRIPTS)) + ctx->mark_char_map['~'] = 1; + + if(ctx->parser.flags & MD_FLAG_SUPERSCRIPTS) + ctx->mark_char_map['^'] = 1; + + if(ctx->parser.flags & MD_FLAG_LATEXMATHSPANS) + ctx->mark_char_map['$'] = 1; + + if(ctx->parser.flags & MD_FLAG_HIGHLIGHT) + ctx->mark_char_map['='] = 1; + + if(ctx->parser.flags & MD_FLAG_INSERT) + ctx->mark_char_map['+'] = 1; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEEMAILAUTOLINKS) + ctx->mark_char_map['@'] = 1; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEURLAUTOLINKS) + ctx->mark_char_map[':'] = 1; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEWWWAUTOLINKS) + ctx->mark_char_map['.'] = 1; + + if((ctx->parser.flags & MD_FLAG_TABLES) || (ctx->parser.flags & MD_FLAG_WIKILINKS) || + (ctx->parser.flags & MD_FLAG_SPOILERS)) + ctx->mark_char_map['|'] = 1; + + if(ctx->parser.flags & MD_FLAG_COLLAPSEWHITESPACE) { + int i; + + for(i = 0; i < (int) sizeof(ctx->mark_char_map); i++) { + if(ISWHITESPACE_(i)) + ctx->mark_char_map[i] = 1; + } + } +} + +static int +md_is_code_span(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, + MD_MARK* opener, MD_MARK* closer, + OFF last_potential_closers[CODESPAN_MARK_MAXLEN], + int* p_reached_paragraph_end) +{ + OFF opener_beg = beg; + OFF opener_end; + OFF closer_beg; + OFF closer_end; + SZ mark_len; + OFF line_end; + int has_space_after_opener = false; + int has_eol_after_opener = false; + int has_space_before_closer = false; + int has_eol_before_closer = false; + int has_only_space = true; + MD_SIZE line_index = 0; + + line_end = lines[0].end; + opener_end = opener_beg; + while(opener_end < line_end && CH(opener_end) == _T('`')) + opener_end++; + has_space_after_opener = (opener_end < line_end && CH(opener_end) == _T(' ')); + has_eol_after_opener = (opener_end == line_end); + + /* The caller needs to know end of the opening mark even if we fail. */ + opener->end = opener_end; + + mark_len = opener_end - opener_beg; + if(mark_len > CODESPAN_MARK_MAXLEN) + return false; + + /* Check whether we already know there is no closer of this length. + * If so, re-scan does no sense. This fixes issue #59. */ + if(last_potential_closers[mark_len-1] >= lines[n_lines-1].end || + (*p_reached_paragraph_end && last_potential_closers[mark_len-1] < opener_end)) + return false; + + closer_beg = opener_end; + closer_end = opener_end; + + /* Find closer mark. */ + while(true) { + while(closer_beg < line_end && CH(closer_beg) != _T('`')) { + if(CH(closer_beg) != _T(' ')) + has_only_space = false; + closer_beg++; + } + closer_end = closer_beg; + while(closer_end < line_end && CH(closer_end) == _T('`')) + closer_end++; + + if(closer_end - closer_beg == mark_len) { + /* Success. */ + has_space_before_closer = (closer_beg > lines[line_index].beg && CH(closer_beg-1) == _T(' ')); + has_eol_before_closer = (closer_beg == lines[line_index].beg); + break; + } + + if(closer_end - closer_beg > 0) { + /* We have found a back-tick which is not part of the closer. */ + has_only_space = false; + + /* But if we eventually fail, remember it as a potential closer + * of its own length for future attempts. This mitigates needs for + * rescans. */ + if(closer_end - closer_beg < CODESPAN_MARK_MAXLEN) { + if(closer_beg > last_potential_closers[closer_end - closer_beg - 1]) + last_potential_closers[closer_end - closer_beg - 1] = closer_beg; + } + } + + if(closer_end >= line_end) { + line_index++; + if(line_index >= n_lines) { + /* Reached end of the paragraph and still nothing. */ + *p_reached_paragraph_end = true; + return false; + } + /* Try on the next line. */ + line_end = lines[line_index].end; + closer_beg = lines[line_index].beg; + } else { + closer_beg = closer_end; + } + } + + /* If there is a space or a new line both after and before the opener + * (and if the code span is not made of spaces only), consume one initial + * and one trailing space as part of the marks. */ + if(!has_only_space && + (has_space_after_opener || has_eol_after_opener) && + (has_space_before_closer || has_eol_before_closer)) + { + if(has_space_after_opener) + opener_end++; + else + opener_end = lines[1].beg; + + if(has_space_before_closer) + closer_beg--; + else { + /* Go back to the end of prev line */ + closer_beg = lines[line_index-1].end; + /* But restore any trailing whitespace */ + while(closer_beg < ctx->size && ISBLANK(closer_beg)) + closer_beg++; + } + } + + opener->ch = _T('`'); + opener->beg = opener_beg; + opener->end = opener_end; + opener->flags = MD_MARK_POTENTIAL_OPENER; + closer->ch = _T('`'); + closer->beg = closer_beg; + closer->end = closer_end; + closer->flags = MD_MARK_POTENTIAL_CLOSER; + return true; +} + +static int +md_is_autolink_uri(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg+1; + + MD_ASSERT(CH(beg) == _T('<')); + + /* Check for scheme. */ + if(off >= max_end || !ISALNUM(off)) + return false; + off++; + while(1) { + if(off >= max_end) + return false; + if(off - beg > 32) + return false; + if(CH(off) == _T(':') && off - beg >= 3) + break; + if(!ISALNUM(off) && CH(off) != _T('+') && CH(off) != _T('-') && CH(off) != _T('.')) + return false; + off++; + } + + /* Check the path after the scheme. */ + while(off < max_end && CH(off) != _T('>')) { + if(ISWHITESPACE(off) || ISCNTRL(off) || CH(off) == _T('<')) + return false; + off++; + } + + if(off >= max_end) + return false; + + MD_ASSERT(CH(off) == _T('>')); + *p_end = off+1; + return true; +} + +static int +md_is_autolink_email(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg + 1; + int label_len; + + MD_ASSERT(CH(beg) == _T('<')); + + /* The code should correspond to this regexp: + /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+ + @[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? + (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ + */ + + /* Username (before '@'). */ + while(off < max_end && (ISALNUM(off) || ISANYOF(off, _T(".!#$%&'*+/=?^_`{|}~-")))) + off++; + if(off <= beg+1) + return false; + + /* '@' */ + if(off >= max_end || CH(off) != _T('@')) + return false; + off++; + + /* Labels delimited with '.'; each label is sequence of 1 - 63 alnum + * characters or '-', but '-' is not allowed as first or last char. */ + label_len = 0; + while(off < max_end) { + if(ISALNUM(off)) + label_len++; + else if(CH(off) == _T('-') && label_len > 0) + label_len++; + else if(CH(off) == _T('.') && label_len > 0 && CH(off-1) != _T('-')) + label_len = 0; + else + break; + + if(label_len > 63) + return false; + + off++; + } + + if(label_len <= 0 || off >= max_end || CH(off) != _T('>') || CH(off-1) == _T('-')) + return false; + + *p_end = off+1; + return true; +} + +static int +md_is_autolink(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, int* p_missing_mailto) +{ + if(md_is_autolink_uri(ctx, beg, max_end, p_end)) { + *p_missing_mailto = false; + return true; + } + + if(md_is_autolink_email(ctx, beg, max_end, p_end)) { + *p_missing_mailto = true; + return true; + } + + return false; +} + +static int +md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int table_mode) +{ + MD_SIZE line_index; + int ret = 0; + MD_MARK* mark; + OFF codespan_last_potential_closers[CODESPAN_MARK_MAXLEN] = { 0 }; + int codespan_scanned_till_paragraph_end = false; + + for(line_index = 0; line_index < n_lines; line_index++) { + const MD_LINE* line = &lines[line_index]; + OFF off = line->beg; + + while(true) { + CHAR ch; + +#ifdef MD4C_USE_UTF16 + /* For UTF-16, mark_char_map[] covers only ASCII. */ + #define IS_MARK_CHAR(off) ((CH(off) < SIZEOF_ARRAY(ctx->mark_char_map)) && \ + (ctx->mark_char_map[(unsigned char) CH(off)])) +#else + /* For 8-bit encodings, mark_char_map[] covers all 256 elements. */ + #define IS_MARK_CHAR(off) (ctx->mark_char_map[(unsigned char) CH(off)]) +#endif + + /* Optimization: Use some loop unrolling. */ + while(off + 3 < line->end && !IS_MARK_CHAR(off+0) && !IS_MARK_CHAR(off+1) + && !IS_MARK_CHAR(off+2) && !IS_MARK_CHAR(off+3)) + off += 4; + while(off < line->end && !IS_MARK_CHAR(off+0)) + off++; + + if(off >= line->end) + break; + + ch = CH(off); + + /* A backslash escape. + * It can go beyond line->end as it may involve escaped new + * line to form a hard break. */ + if(ch == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) { + /* Hard-break cannot be on the last line of the block. */ + if(!ISNEWLINE(off+1) || line_index+1 < n_lines) + ADD_MARK(ch, off, off+2, MD_MARK_RESOLVED); + off += 2; + continue; + } + + /* A potential (string) emphasis start/end. */ + if(ch == _T('*') || ch == _T('_')) { + OFF tmp = off+1; + int left_level; /* What precedes: 0 = whitespace; 1 = punctuation; 2 = other char. */ + int right_level; /* What follows: 0 = whitespace; 1 = punctuation; 2 = other char. */ + + while(tmp < line->end && CH(tmp) == ch) + tmp++; + + if(off == line->beg || ISUNICODEWHITESPACEBEFORE(off)) + left_level = 0; + else if(ISUNICODEPUNCTBEFORE(off)) + left_level = 1; + else + left_level = 2; + + if(tmp == line->end || ISUNICODEWHITESPACE(tmp)) + right_level = 0; + else if(ISUNICODEPUNCT(tmp)) + right_level = 1; + else + right_level = 2; + + /* Intra-word underscore doesn't have special meaning. */ + if(ch == _T('_') && left_level == 2 && right_level == 2) { + left_level = 0; + right_level = 0; + } + + if(left_level != 0 || right_level != 0) { + unsigned flags = 0; + + if(left_level > 0 && left_level >= right_level) + flags |= MD_MARK_POTENTIAL_CLOSER; + if(right_level > 0 && right_level >= left_level) + flags |= MD_MARK_POTENTIAL_OPENER; + if(flags == (MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER)) + flags |= MD_MARK_EMPH_OC; + + /* For "the rule of three" we need to remember the original + * size of the mark (modulo three), before we potentially + * split the mark when being later resolved partially by some + * shorter closer. */ + switch((tmp - off) % 3) { + case 0: flags |= MD_MARK_EMPH_MOD3_0; break; + case 1: flags |= MD_MARK_EMPH_MOD3_1; break; + case 2: flags |= MD_MARK_EMPH_MOD3_2; break; + } + + ADD_MARK(ch, off, tmp, flags); + + /* During resolving, multiple asterisks may have to be + * split into independent span start/ends. Consider e.g. + * "**foo* bar*". Therefore we push also some empty dummy + * marks to have enough space for that. */ + off++; + while(off < tmp) { + ADD_MARK('D', off, off, 0); + off++; + } + continue; + } + + off = tmp; + continue; + } + + /* A potential code span start/end. */ + if(ch == _T('`')) { + MD_MARK opener; + MD_MARK closer; + int is_code_span; + + is_code_span = md_is_code_span(ctx, line, n_lines - line_index, off, + &opener, &closer, codespan_last_potential_closers, + &codespan_scanned_till_paragraph_end); + if(is_code_span) { + ADD_MARK(opener.ch, opener.beg, opener.end, opener.flags); + ADD_MARK(closer.ch, closer.beg, closer.end, closer.flags); + md_resolve_range(ctx, ctx->n_marks-2, ctx->n_marks-1); + off = closer.end; + + /* Advance the current line accordingly. */ + if(off > line->end) + line = md_lookup_line(off, lines, n_lines, &line_index); + continue; + } + + off = opener.end; + continue; + } + + /* A potential entity start. */ + if(ch == _T('&')) { + ADD_MARK(ch, off, off+1, MD_MARK_POTENTIAL_OPENER); + off++; + continue; + } + + /* A potential entity end. */ + if(ch == _T(';')) { + /* We surely cannot be entity unless the previous mark is '&'. */ + if(ctx->n_marks > 0 && ctx->marks[ctx->n_marks-1].ch == _T('&')) + ADD_MARK(ch, off, off+1, MD_MARK_POTENTIAL_CLOSER); + + off++; + continue; + } + + /* A potential autolink or raw HTML start/end. */ + if(ch == _T('<')) { + int is_autolink; + OFF autolink_end; + int missing_mailto; + + if(!(ctx->parser.flags & MD_FLAG_NOHTMLSPANS)) { + int is_html; + OFF html_end; + + /* Given the nature of the raw HTML, we have to recognize + * it here. Doing so later in md_analyze_lt_gt() could + * open can of worms of quadratic complexity. */ + is_html = md_is_html_any(ctx, line, n_lines - line_index, off, + lines[n_lines-1].end, &html_end); + if(is_html) { + ADD_MARK(_T('<'), off, off, MD_MARK_OPENER | MD_MARK_RESOLVED); + ADD_MARK(_T('>'), html_end, html_end, MD_MARK_CLOSER | MD_MARK_RESOLVED); + ctx->marks[ctx->n_marks-2].next = ctx->n_marks-1; + ctx->marks[ctx->n_marks-1].prev = ctx->n_marks-2; + off = html_end; + + /* Advance the current line accordingly. */ + if(off > line->end) + line = md_lookup_line(off, lines, n_lines, &line_index); + continue; + } + } + + is_autolink = md_is_autolink(ctx, off, lines[n_lines-1].end, + &autolink_end, &missing_mailto); + if(is_autolink) { + unsigned flags = MD_MARK_RESOLVED | MD_MARK_AUTOLINK; + if(missing_mailto) + flags |= MD_MARK_AUTOLINK_MISSING_MAILTO; + + ADD_MARK(_T('<'), off, off+1, MD_MARK_OPENER | flags); + ADD_MARK(_T('>'), autolink_end-1, autolink_end, MD_MARK_CLOSER | flags); + ctx->marks[ctx->n_marks-2].next = ctx->n_marks-1; + ctx->marks[ctx->n_marks-1].prev = ctx->n_marks-2; + off = autolink_end; + continue; + } + + off++; + continue; + } + + /* A potential link, footnote and similar or its part. */ + if(ch == _T('[') || (ch == _T('!') && off+1 < line->end && CH(off+1) == _T('['))) { + if(ch == _T('!')) { + ADD_MARK(ch, off+1, off+2, MD_MARK_POTENTIAL_OPENER | MD_MARK_BRACKET_CANBEIMAGE); + off += 2; + } else { + ADD_MARK(ch, off, off+1, MD_MARK_POTENTIAL_OPENER); + off += 1; + } + + /* Two dummies to make enough place for data we need if it is + * a link. */ + ADD_MARK('D', off, off, 0); + ADD_MARK('D', off, off, 0); + continue; + } + if(ch == _T(']')) { + ADD_MARK(ch, off, off+1, MD_MARK_POTENTIAL_CLOSER); + off++; + continue; + } + + /* A potential permissive e-mail autolink. */ + if(ch == _T('@')) { + if(line->beg + 1 <= off && ISALNUM(off-1) && + off + 3 < line->end && ISALNUM(off+1)) + { + ADD_MARK(ch, off, off+1, MD_MARK_POTENTIAL_OPENER); + /* Push a dummy as a reserve for a closer. */ + ADD_MARK('D', line->beg, line->end, 0); + } + + off++; + continue; + } + + /* A potential permissive URL autolink. */ + if(ch == _T(':')) { + static const struct { + const CHAR* scheme; + SZ scheme_size; + const CHAR* suffix; + SZ suffix_size; + } scheme_map[] = { + /* In the order from the most frequently used, arguably. */ + { _T("http"), 4, _T("//"), 2 }, + { _T("https"), 5, _T("//"), 2 }, + { _T("ftp"), 3, _T("//"), 2 } + }; + int scheme_index; + + for(scheme_index = 0; scheme_index < (int) SIZEOF_ARRAY(scheme_map); scheme_index++) { + const CHAR* scheme = scheme_map[scheme_index].scheme; + const SZ scheme_size = scheme_map[scheme_index].scheme_size; + const CHAR* suffix = scheme_map[scheme_index].suffix; + const SZ suffix_size = scheme_map[scheme_index].suffix_size; + + if(line->beg + scheme_size <= off && md_ascii_eq(STR(off-scheme_size), scheme, scheme_size) && + off + 1 + suffix_size < line->end && md_ascii_eq(STR(off+1), suffix, suffix_size)) + { + ADD_MARK(ch, off-scheme_size, off+1+suffix_size, MD_MARK_POTENTIAL_OPENER); + /* Push a dummy as a reserve for a closer. */ + ADD_MARK('D', line->beg, line->end, 0); + off += 1 + suffix_size; + break; + } + } + + off++; + continue; + } + + /* A potential permissive WWW autolink. */ + if(ch == _T('.')) { + if(line->beg + 3 <= off && md_ascii_eq(STR(off-3), _T("www"), 3) && + (off-3 == line->beg || ISUNICODEWHITESPACEBEFORE(off-3) || ISUNICODEPUNCTBEFORE(off-3))) + { + ADD_MARK(ch, off-3, off+1, MD_MARK_POTENTIAL_OPENER); + /* Push a dummy as a reserve for a closer. */ + ADD_MARK('D', line->beg, line->end, 0); + off++; + continue; + } + + off++; + continue; + } + + /* We may need pipes for tables (cell delimiter), for wiki-links + * Note we coalesce spans of pipes into a single mark. + * + * - Tables may use spans of any length. + * - Wiki-links use only (unresolved) spans of length 1. + * - Spoilers use use only (unresolved) spans of length 2. + */ + if(ch == _T('|')) { + OFF tmp = off + 1; + while(tmp < line->end && CH(tmp) == _T('|')) + tmp++; + if(table_mode || + (tmp - off == 1 && (ctx->parser.flags & MD_FLAG_WIKILINKS)) || + (tmp - off == 2 && (ctx->parser.flags & MD_FLAG_SPOILERS))) + ADD_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER); + off = tmp; + continue; + } + + /* A potential superscript start/end: ^text^ */ + if(ch == _T('^') && (ctx->parser.flags & MD_FLAG_SUPERSCRIPTS)) { + OFF tmp = off + 1; + + while(tmp < line->end && CH(tmp) == _T('^')) + tmp++; + + /* Only a single caret is a superscript delimiter; longer runs are literal. */ + if(tmp - off == 1) { + unsigned flags = MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER; + + /* Cannot open before whitespace; cannot close after whitespace. */ + if(off + 1 >= line->end || ISUNICODEWHITESPACE(off + 1)) + flags &= ~MD_MARK_POTENTIAL_OPENER; + if(off == line->beg || ISUNICODEWHITESPACEBEFORE(off)) + flags &= ~MD_MARK_POTENTIAL_CLOSER; + if(flags != 0) + ADD_MARK(ch, off, off + 1, flags); + } + + off = tmp; + continue; + } + + /* A potential highlight start/end: ==text== */ + if(ch == _T('=') && (ctx->parser.flags & MD_FLAG_HIGHLIGHT)) { + OFF tmp = off + 1; + + while(tmp < line->end && CH(tmp) == _T('=')) + tmp++; + + /* Only exactly two equals signs form a highlight delimiter. */ + if(tmp - off == 2) { + unsigned flags = MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER; + + /* Cannot open before whitespace; cannot close after whitespace. */ + if(tmp >= line->end || ISUNICODEWHITESPACE(tmp)) + flags &= ~MD_MARK_POTENTIAL_OPENER; + if(off == line->beg || ISUNICODEWHITESPACEBEFORE(off)) + flags &= ~MD_MARK_POTENTIAL_CLOSER; + if(flags != 0) + ADD_MARK(ch, off, tmp, flags); + } + + off = tmp; + continue; + } + + /* A potential insert start/end: ++text++ */ + if(ch == _T('+') && (ctx->parser.flags & MD_FLAG_INSERT)) { + OFF tmp = off + 1; + + while(tmp < line->end && CH(tmp) == _T('+')) + tmp++; + + /* Only exactly two plus signs form a insert delimiter. */ + if(tmp - off == 2) { + unsigned flags = MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER; + + /* Cannot open before whitespace; cannot close after whitespace. */ + if(tmp >= line->end || ISUNICODEWHITESPACE(tmp)) + flags &= ~MD_MARK_POTENTIAL_OPENER; + if(off == line->beg || ISUNICODEWHITESPACEBEFORE(off)) + flags &= ~MD_MARK_POTENTIAL_CLOSER; + if(flags != 0) + ADD_MARK(ch, off, tmp, flags); + } + + off = tmp; + continue; + } + + /* A potential strikethrough/subscript start/end. */ + if(ch == _T('~')) { + OFF tmp = off + 1; + + while(tmp < line->end && CH(tmp) == _T('~')) + tmp++; + + if(tmp - off == 1 && (ctx->parser.flags & MD_FLAG_SUBSCRIPTS)) { + /* Subscript: can open after any non-whitespace, cannot open + * before whitespace; cannot close after whitespace. */ + unsigned flags = MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER; + + if(off + 1 >= line->end || ISUNICODEWHITESPACE(off + 1)) + flags &= ~MD_MARK_POTENTIAL_OPENER; + if(off == line->beg || ISUNICODEWHITESPACEBEFORE(off)) + flags &= ~MD_MARK_POTENTIAL_CLOSER; + if(flags != 0) + ADD_MARK(ch, off, off + 1, flags); + } else if(tmp - off <= 2 && (ctx->parser.flags & MD_FLAG_STRIKETHROUGH)) { + /* Strikethrough: standard GFM left/right-flanking rules. */ + unsigned flags = MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER; + + if(off > line->beg && !ISUNICODEWHITESPACEBEFORE(off) && !ISUNICODEPUNCTBEFORE(off)) + flags &= ~MD_MARK_POTENTIAL_OPENER; + if(tmp < line->end && !ISUNICODEWHITESPACE(tmp) && !ISUNICODEPUNCT(tmp)) + flags &= ~MD_MARK_POTENTIAL_CLOSER; + if(flags != 0) + ADD_MARK(ch, off, tmp, flags); + } + + off = tmp; + continue; + } + + /* A potential equation start/end. */ + if(ch == _T('$')) { + OFF tmp = off + 1; + + while(tmp < line->end && CH(tmp) == _T('$')) + tmp++; + + if(tmp - off <= 2) { + unsigned flags = MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER; + + if(off > line->beg && !ISUNICODEWHITESPACEBEFORE(off) && !ISUNICODEPUNCTBEFORE(off)) + flags &= ~MD_MARK_POTENTIAL_OPENER; + if(tmp < line->end && !ISUNICODEWHITESPACE(tmp) && !ISUNICODEPUNCT(tmp)) + flags &= ~MD_MARK_POTENTIAL_CLOSER; + if(flags != 0) + ADD_MARK(ch, off, tmp, flags); + } + + off = tmp; + continue; + } + + /* Turn non-trivial whitespace into single space. */ + if(ISWHITESPACE_(ch)) { + OFF tmp = off+1; + + while(tmp < line->end && ISWHITESPACE(tmp)) + tmp++; + + if(tmp - off > 1 || ch != _T(' ')) + ADD_MARK(ch, off, tmp, MD_MARK_RESOLVED); + + off = tmp; + continue; + } + + /* NULL character. */ + if(ch == _T('\0')) { + ADD_MARK(ch, off, off+1, MD_MARK_RESOLVED); + off++; + continue; + } + + off++; + } + } + + /* Add a dummy mark at the end of the mark vector to simplify + * process_inlines(). */ + ADD_MARK(127, ctx->size, ctx->size, MD_MARK_RESOLVED); + +abort: + return ret; +} + +static void +md_analyze_bracket(MD_CTX* ctx, int mark_index) +{ + /* We cannot really resolve links here as for that we would need + * more context. E.g. a following pair of brackets (reference link), + * or enclosing pair of brackets (if the inner is the link, the outer + * one cannot be.) + * + * Therefore we here only construct a list of '[' ']' pairs ordered by + * position of the closer. This allows us to analyze what is or is not + * link in the right order, from inside to outside in case of nested + * brackets. + * + * The resolving itself is deferred to md_resolve_brackets(). + */ + + MD_MARK* mark = &ctx->marks[mark_index]; + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) { + if(BRACKET_OPENERS.top >= 0) + ctx->marks[BRACKET_OPENERS.top].flags |= MD_MARK_BRACKET_HASNESTED; + + md_mark_stack_push(ctx, &BRACKET_OPENERS, mark_index); + return; + } + + if(BRACKET_OPENERS.top >= 0) { + int opener_index = md_mark_stack_pop(ctx, &BRACKET_OPENERS); + MD_MARK* opener = &ctx->marks[opener_index]; + + /* Interconnect the opener and closer. */ + opener->next = mark_index; + mark->prev = opener_index; + + /* Add the pair into a list of potential brackets for md_resolve_brackets(). + * Note we misuse opener->prev for this as opener->next points to its + * closer. */ + if(ctx->unresolved_link_tail >= 0) + ctx->marks[ctx->unresolved_link_tail].prev = opener_index; + else + ctx->unresolved_link_head = opener_index; + ctx->unresolved_link_tail = opener_index; + opener->prev = -1; + } +} + +/* Forward declaration. */ +static void md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, + int mark_beg, int mark_end); + +/* Try to resolve a bracket pair as a wiki link '[[destination]]' or + * '[[destination|label]]'. + * Returns true if resolved, false if not a wiki link, -1 on error. */ +static int +md_resolve_bracket_wikilink(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, + int opener_index, int closer_index, + MD_MARK* opener, MD_MARK* closer, + MD_MARK* next_opener, MD_MARK* next_closer, + OFF* last_link_beg, OFF* last_link_end, + int* p_opener_index) +{ + MD_MARK* delim = NULL; + int delim_index; + OFF dest_beg, dest_end; + OFF off; + + if(!(ctx->parser.flags & MD_FLAG_WIKILINKS)) + return false; + + if(opener->ch != _T('[') || opener->end - opener->beg != 1 || + next_opener == NULL || next_opener->ch != _T('[') || next_opener->end - next_opener->beg != 1 || + next_closer == NULL || next_closer->ch != _T(']') || next_closer->end - next_closer->beg != 1) + return false; + + /* Check that the next_opener and next_closer are nested properly. */ + if(next_opener->beg != opener->beg - 1 || next_closer->beg != closer->beg + 1) + return false; + + /* We don't allow destination to be longer than 100 characters. + * Lets scan to see whether there is '|'. (If not then the whole + * wiki-link has to be below the 100 characters.) */ + delim_index = opener_index + 1; + while(delim_index < closer_index) { + MD_MARK* m = &ctx->marks[delim_index]; + if(m->ch == _T('|') && m->end - m->beg == 1 && !(m->flags & MD_MARK_RESOLVED)) { + delim = m; + break; + } + if(m->ch != _T('D')) { + if(m->beg - opener->end > 100) + break; + if(m->ch != _T('D') && (m->flags & MD_MARK_OPENER)) + delim_index = m->next; + } + delim_index++; + } + + dest_beg = opener->end; + dest_end = (delim != NULL) ? delim->beg : closer->beg; + if(dest_end - dest_beg == 0 || dest_end - dest_beg > 100) + return false; + + /* There may not be any new line in the destination. */ + for(off = dest_beg; off < dest_end; off++) { + if(ISNEWLINE(off)) + return false; + } + + md_pop_openers(ctx, opener_index); + + if(delim != NULL) { + if(delim->end < closer->beg) { + md_disable_marks(ctx, opener_index+1, delim_index); + delim->flags |= MD_MARK_RESOLVED; + opener->end = delim->beg; + } else { + /* The pipe is just before the closer: [[foo|]] */ + md_disable_marks(ctx, opener_index+1, closer_index); + closer->beg = delim->beg; + } + } + + opener->beg = next_opener->beg; + closer->end = next_closer->end; + md_resolve_range(ctx, opener_index, closer_index); + + *last_link_beg = opener->beg; + *last_link_end = closer->end; + + if(delim != NULL) + md_analyze_link_contents(ctx, lines, n_lines, delim_index+1, closer_index); + + *p_opener_index = next_opener->prev; + return true; +} + +/* Resolve footnote references [^label] in the current block. */ +static int +md_resolve_bracket_footnote(MD_CTX* ctx, MD_MARK* opener, MD_MARK* closer, + OFF* last_link_beg, OFF* last_link_end, + int* p_opener_index) +{ + MD_MARK* index_mark; + MD_FOOTNOTE_DEF* def; + OFF label_beg, label_end; + + if(!(ctx->parser.flags & MD_FLAG_FOOTNOTES)) + return false; + if(opener->ch != _T('[') || opener->end >= ctx->size || CH(opener->end) != _T('^')) + return false; + + /* Expand the opener to eat the '^' */ + opener->end++; + closer = &ctx->marks[opener->next]; + + /* Verify the label satisfies the label rules. */ + label_beg = opener->end; + if(!md_is_footnote_label(ctx, label_beg, &label_end) || label_end != closer->beg) + return false; + + if(label_beg >= label_end) + return false; /* empty label */ + + def = md_lookup_footnote_def(ctx, STR(label_beg), label_end - label_beg); + if(def == NULL) + return false; + + /* Assign index on first reference. */ + if(def->index == 0) + def->index = ++ctx->next_footnote_index; + def->ref_count++; + + /* Store the public callback details in the dummy mark after the opener. */ + index_mark = opener + 1; + MD_ASSERT(index_mark->ch == _T('D')); + index_mark->beg = def->index; + index_mark->end = def->ref_count; + + /* Mark as resolved. */ + opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED | MD_MARK_BRACKET_FOOTNOTEREF; + closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED | MD_MARK_BRACKET_FOOTNOTEREF; + *last_link_beg = opener->beg; + *last_link_end = closer->end; + + *p_opener_index = opener->prev; + return true; +} + +/* Try to resolve a bracket pair as a CommonMark link or image. + * Returns -1 on error, 0 otherwise. */ +static int +md_resolve_bracket_link(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, + int opener_index, int closer_index, + MD_MARK* opener, MD_MARK* closer, + MD_MARK* next_opener, MD_MARK* next_closer, + int* p_next_index, + OFF* last_link_beg, OFF* last_link_end, + OFF* last_img_beg, OFF* last_img_end) +{ + MD_LINK_ATTR attr; + int is_link = false; + + if(next_opener != NULL && next_opener->beg == closer->end) { + if(next_closer->beg > closer->end + 1) { + /* Might be full reference link. */ + if(!(next_opener->flags & MD_MARK_BRACKET_HASNESTED)) + is_link = md_is_link_reference(ctx, lines, n_lines, next_opener->beg, next_closer->end, &attr); + } else { + /* Might be shortcut reference link. */ + if(!(opener->flags & MD_MARK_BRACKET_HASNESTED)) + is_link = md_is_link_reference(ctx, lines, n_lines, opener->beg, closer->end, &attr); + } + + if(is_link < 0) + return -1; + + if(is_link) { + /* Eat the 2nd "[...]". */ + closer->end = next_closer->end; + + /* Do not analyze the label as a standalone link in the next + * iteration. */ + *p_next_index = ctx->marks[*p_next_index].prev; + } + } else { + if(closer->end < ctx->size && CH(closer->end) == _T('(')) { + /* Might be inline link. */ + OFF inline_link_end = UINT_MAX; + int following_mark_index = closer_index + 1; + + is_link = md_is_inline_link_spec(ctx, lines, n_lines, closer->end, &inline_link_end, &attr); + if(is_link < 0) + return -1; + + /* Check the closing ')' is not inside an already resolved range + * (i.e. a range with a higher priority), e.g. a code span. */ + if(is_link) { + while(following_mark_index < ctx->n_marks) { + MD_MARK* mark = &ctx->marks[following_mark_index]; + + if(mark->beg >= inline_link_end) + break; + if((mark->flags & (MD_MARK_OPENER | MD_MARK_RESOLVED)) == (MD_MARK_OPENER | MD_MARK_RESOLVED)) { + if(ctx->marks[mark->next].beg >= inline_link_end) { + /* Cancel the link status. */ + if(attr.title_needs_free) + free(attr.title); + is_link = false; + break; + } + + following_mark_index = mark->next + 1; + } else { + following_mark_index++; + } + } + } + + if(is_link) { + /* Eat the "(...)" */ + closer->end = inline_link_end; + md_disable_marks(ctx, closer_index+1, following_mark_index); + } + } + + if(!is_link) { + /* Might be collapsed reference link. */ + if(!(opener->flags & MD_MARK_BRACKET_HASNESTED)) + is_link = md_is_link_reference(ctx, lines, n_lines, opener->beg, closer->end, &attr); + if(is_link < 0) + return -1; + } + } + + if(is_link) { + /* Resolve the brackets as a link. */ + opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED; + closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED; + + /* If it is a link, we store the destination and title in the two + * dummy marks after the opener. */ + MD_ASSERT(ctx->marks[opener_index+1].ch == _T('D')); + ctx->marks[opener_index+1].beg = attr.dest_beg; + ctx->marks[opener_index+1].end = attr.dest_end; + + MD_ASSERT(ctx->marks[opener_index+2].ch == _T('D')); + md_mark_store_ptr(ctx, opener_index+2, attr.title); + /* The title might or might not have been allocated for us. */ + if(attr.title_needs_free) + md_mark_stack_push(ctx, &ctx->ptr_stack, opener_index+2); + ctx->marks[opener_index+2].prev = attr.title_size; + + if(opener->ch == _T('[')) { + *last_link_beg = opener->beg; + *last_link_end = closer->end; + } else { + *last_img_beg = opener->beg; + *last_img_end = closer->end; + } + + md_analyze_link_contents(ctx, lines, n_lines, opener_index+1, closer_index); + + /* If the link text is formed by nothing but permissive autolink, + * suppress the autolink. + * See https://github.com/mity/md4c/issues/152 for more info. */ + if(ctx->parser.flags & MD_FLAG_PERMISSIVEAUTOLINKS) { + MD_MARK* first_nested; + MD_MARK* last_nested; + + first_nested = opener + 1; + while(first_nested->ch == _T('D') && first_nested < closer) + first_nested++; + + last_nested = closer - 1; + while(first_nested->ch == _T('D') && last_nested > opener) + last_nested--; + + if((first_nested->flags & MD_MARK_RESOLVED) && + first_nested->beg == opener->end && + ISANYOF_(first_nested->ch, _T("@:.")) && + first_nested->next == (last_nested - ctx->marks) && + last_nested->end == closer->beg) + { + first_nested->ch = _T('D'); + first_nested->flags &= ~MD_MARK_RESOLVED; + last_nested->ch = _T('D'); + last_nested->flags &= ~MD_MARK_RESOLVED; + } + } + } + + return 0; +} + +/* Resolve bracket pairs as links, wiki links, or (in a 2nd pass) footnotes. */ +static int +md_resolve_brackets(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) +{ + int opener_index = ctx->unresolved_link_head; + OFF last_link_beg = 0; + OFF last_link_end = 0; + OFF last_img_beg = 0; + OFF last_img_end = 0; + int ret; + + /* Note we here analyze from inner to outer as the marks are ordered + * by closer->beg. */ + while(opener_index >= 0) { + MD_MARK* opener = &ctx->marks[opener_index]; + int closer_index = opener->next; + MD_MARK* closer = &ctx->marks[closer_index]; + int next_index = opener->prev; + MD_MARK* next_opener; + MD_MARK* next_closer; + + if(opener->ch == _T('D')) { + /* We could have this disabled in previous iterations, and + * processing would be just burning CPU cycles. */ + opener_index = next_index; + continue; + } + + if(next_index >= 0) { + next_opener = &ctx->marks[next_index]; + next_closer = &ctx->marks[next_opener->next]; + } else { + next_opener = NULL; + next_closer = NULL; + } + + /* We can perhaps be an image? */ + if(opener->flags & MD_MARK_BRACKET_CANBEIMAGE) { + opener->ch = _T('!'); + opener->beg--; + } + + /* If nested ("[ [ ] ]"), we need to make sure that: + * - The outer does not end inside of (...) belonging to the inner. + * - The outer cannot be link if the inner is link (but this does not apply to images). */ + if((opener->beg < last_link_beg && closer->end < last_link_end) || + (opener->beg < last_img_beg && closer->end < last_img_end) || + (opener->beg < last_link_end && opener->ch != _T('!'))) + { + opener_index = next_index; + continue; + } + + ret = md_resolve_bracket_footnote(ctx, opener, closer, + &last_link_beg, &last_link_end, &opener_index); + if(ret < 0) + return -1; + if(ret > 0) + continue; + + ret = md_resolve_bracket_wikilink(ctx, lines, n_lines, opener_index, closer_index, + opener, closer, next_opener, next_closer, + &last_link_beg, &last_link_end, &opener_index); + if(ret < 0) + return -1; + if(ret > 0) + continue; + + ret = md_resolve_bracket_link(ctx, lines, n_lines, opener_index, closer_index, + opener, closer, next_opener, next_closer, &next_index, + &last_link_beg, &last_link_end, &last_img_beg, &last_img_end); + if(ret < 0) + return -1; + + opener_index = next_index; + } + + return 0; +} + +/* Analyze whether the mark '&' starts a HTML entity. + * If so, update its flags as well as flags of corresponding closer ';'. */ +static void +md_analyze_entity(MD_CTX* ctx, int mark_index) +{ + MD_MARK* opener = &ctx->marks[mark_index]; + MD_MARK* closer; + OFF off; + + /* Cannot be entity if there is no closer as the next mark. + * (Any other mark between would mean strange character which cannot be + * part of the entity. + * + * So we can do all the work on '&' and do not call this later for the + * closing mark ';'. + */ + if(mark_index + 1 >= ctx->n_marks) + return; + closer = &ctx->marks[mark_index+1]; + if(closer->ch != ';') + return; + + if(md_is_entity(ctx, opener->beg, closer->end, &off)) { + MD_ASSERT(off == closer->end); + + md_resolve_range(ctx, mark_index, mark_index+1); + opener->end = closer->end; + } +} + +static void +md_analyze_table_cell_boundary(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + /* FIXME: With MD_FLAG_SPOILERS, we reserve double "||" for spoiler marks + * (potentially inside the table). But is it worth it the incompatibility + * with GFM? Perhaps it would be better to disallow spoilers in a table? */ + if((ctx->parser.flags & MD_FLAG_SPOILERS) && mark->end - mark->beg == 2) + return; + + mark->flags |= MD_MARK_RESOLVED; + mark->next = -1; + + if(ctx->table_cell_boundaries_head < 0) + ctx->table_cell_boundaries_head = mark_index; + else + ctx->marks[ctx->table_cell_boundaries_tail].next = mark_index; + ctx->table_cell_boundaries_tail = mark_index; + ctx->n_table_cell_boundaries += mark->end - mark->beg; +} + +/* Split a longer mark into two. The new mark takes the given count of + * characters. May only be called if an adequate number of dummy 'D' marks + * follows. + */ +static int +md_split_emph_mark(MD_CTX* ctx, int mark_index, SZ n) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + int new_mark_index = mark_index + (mark->end - mark->beg - n); + MD_MARK* dummy = &ctx->marks[new_mark_index]; + + MD_ASSERT(mark->end - mark->beg > n); + MD_ASSERT(dummy->ch == 'D'); + + memcpy(dummy, mark, sizeof(MD_MARK)); + mark->end -= n; + dummy->beg = mark->end; + + return new_mark_index; +} + +static void +md_analyze_emph(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + /* If we can be a closer, try to resolve with the preceding opener. */ + if(mark->flags & MD_MARK_POTENTIAL_CLOSER) { + MD_MARK* opener = NULL; + int opener_index = 0; + MD_MARKSTACK* opener_stacks[6]; + int i, n_opener_stacks; + unsigned flags = mark->flags; + + n_opener_stacks = 0; + + /* Apply the rule of 3 */ + opener_stacks[n_opener_stacks++] = md_emph_stack(ctx, mark->ch, MD_MARK_EMPH_MOD3_0 | MD_MARK_EMPH_OC); + if((flags & MD_MARK_EMPH_MOD3_MASK) != MD_MARK_EMPH_MOD3_2) + opener_stacks[n_opener_stacks++] = md_emph_stack(ctx, mark->ch, MD_MARK_EMPH_MOD3_1 | MD_MARK_EMPH_OC); + if((flags & MD_MARK_EMPH_MOD3_MASK) != MD_MARK_EMPH_MOD3_1) + opener_stacks[n_opener_stacks++] = md_emph_stack(ctx, mark->ch, MD_MARK_EMPH_MOD3_2 | MD_MARK_EMPH_OC); + opener_stacks[n_opener_stacks++] = md_emph_stack(ctx, mark->ch, MD_MARK_EMPH_MOD3_0); + if(!(flags & MD_MARK_EMPH_OC) || (flags & MD_MARK_EMPH_MOD3_MASK) != MD_MARK_EMPH_MOD3_2) + opener_stacks[n_opener_stacks++] = md_emph_stack(ctx, mark->ch, MD_MARK_EMPH_MOD3_1); + if(!(flags & MD_MARK_EMPH_OC) || (flags & MD_MARK_EMPH_MOD3_MASK) != MD_MARK_EMPH_MOD3_1) + opener_stacks[n_opener_stacks++] = md_emph_stack(ctx, mark->ch, MD_MARK_EMPH_MOD3_2); + + /* Opener is the most recent mark from the allowed stacks. */ + for(i = 0; i < n_opener_stacks; i++) { + if(opener_stacks[i]->top >= 0) { + int m_index = opener_stacks[i]->top; + MD_MARK* m = &ctx->marks[m_index]; + + if(opener == NULL || m->end > opener->end) { + opener_index = m_index; + opener = m; + } + } + } + + /* Resolve, if we have found matching opener. */ + if(opener != NULL) { + SZ opener_size = opener->end - opener->beg; + SZ closer_size = mark->end - mark->beg; + MD_MARKSTACK* stack = md_opener_stack(ctx, opener_index); + + if(opener_size > closer_size) { + opener_index = md_split_emph_mark(ctx, opener_index, closer_size); + md_mark_stack_push(ctx, stack, opener_index); + } else if(opener_size < closer_size) { + md_split_emph_mark(ctx, mark_index, closer_size - opener_size); + } + + md_pop_openers(ctx, opener_index); + md_resolve_range(ctx, opener_index, mark_index); + return; + } + } + + /* If we could not resolve as closer, we may be yet be an opener. */ + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_stack_push(ctx, md_emph_stack(ctx, mark->ch, mark->flags), mark_index); +} + +static void +md_analyze_tilde(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + MD_MARKSTACK* stack = md_opener_stack(ctx, mark_index); + + /* We attempt to be Github Flavored Markdown compatible here. GFM accepts + * only tildes sequences of length 1 and 2, and the length of the opener + * and closer has to match. */ + + if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && stack->top >= 0) { + int opener_index = stack->top; + + md_pop_openers(ctx, opener_index); + md_resolve_range(ctx, opener_index, mark_index); + return; + } + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_stack_push(ctx, stack, mark_index); +} + +static void +md_analyze_caret(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && CARET_OPENERS.top >= 0) { + int opener_index = CARET_OPENERS.top; + + md_pop_openers(ctx, opener_index); + md_resolve_range(ctx, opener_index, mark_index); + return; + } + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_stack_push(ctx, &CARET_OPENERS, mark_index); +} + +static void +md_analyze_dollar(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && DOLLAR_OPENERS.top >= 0) { + /* If the potential closer has a non-matching number of $, discard */ + MD_MARK* opener = &ctx->marks[DOLLAR_OPENERS.top]; + int opener_index = DOLLAR_OPENERS.top; + MD_MARK* closer = mark; + int closer_index = mark_index; + + if(opener->end - opener->beg == closer->end - closer->beg) { + /* We are the matching closer */ + md_pop_openers(ctx, opener_index); + md_disable_marks(ctx, opener_index+1, closer_index); + md_resolve_range(ctx, opener_index, closer_index); + + /* Discard all pending openers: Latex math span do not allow + * nesting. */ + DOLLAR_OPENERS.top = -1; + return; + } + } + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_stack_push(ctx, &DOLLAR_OPENERS, mark_index); +} + +static void +md_analyze_spoiler(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + /* Only double "||" are recognized as spoiler marks. */ + if((mark->flags & MD_MARK_RESOLVED) || mark->end - mark->beg != 2) + return; + + if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && PIPE_OPENERS.top >= 0) { + int opener_index = PIPE_OPENERS.top; + + md_pop_openers(ctx, opener_index); + md_resolve_range(ctx, opener_index, mark_index); + return; + } + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_stack_push(ctx, &PIPE_OPENERS, mark_index); +} + +static void +md_analyze_highlight(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + /* Only "==" is recognized as a highlight mark. */ + if(mark->end - mark->beg != 2) + return; + + if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && EQUAL_OPENERS.top >= 0) { + int opener_index = EQUAL_OPENERS.top; + + md_pop_openers(ctx, opener_index); + md_resolve_range(ctx, opener_index, mark_index); + return; + } + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_stack_push(ctx, &EQUAL_OPENERS, mark_index); +} + +static void +md_analyze_insert(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + /* Only "++" is recognized as a insert mark. */ + if(mark->end - mark->beg != 2) + return; + + if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && PLUS_OPENERS.top >= 0) { + int opener_index = PLUS_OPENERS.top; + + md_pop_openers(ctx, opener_index); + md_resolve_range(ctx, opener_index, mark_index); + return; + } + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_stack_push(ctx, &PLUS_OPENERS, mark_index); +} + +static MD_MARK* +md_scan_left_for_resolved_mark(MD_CTX* ctx, MD_MARK* mark_from, OFF off, MD_MARK** p_cursor) +{ + MD_MARK* mark; + + for(mark = mark_from; mark >= ctx->marks; mark--) { + if(mark->ch == 'D' || mark->beg > off) + continue; + if(mark->beg <= off && off < mark->end && (mark->flags & MD_MARK_RESOLVED)) { + if(p_cursor != NULL) + *p_cursor = mark; + return mark; + } + if(mark->end <= off) + break; + } + + if(p_cursor != NULL) + *p_cursor = mark; + return NULL; +} + +static MD_MARK* +md_scan_right_for_resolved_mark(MD_CTX* ctx, MD_MARK* mark_from, OFF off, MD_MARK** p_cursor) +{ + MD_MARK* mark; + + for(mark = mark_from; mark < ctx->marks + ctx->n_marks; mark++) { + if(mark->ch == 'D' || mark->end <= off) + continue; + if(mark->beg <= off && off < mark->end && (mark->flags & MD_MARK_RESOLVED)) { + if(p_cursor != NULL) + *p_cursor = mark; + return mark; + } + if(mark->beg > off) + break; + } + + if(p_cursor != NULL) + *p_cursor = mark; + return NULL; +} + +static int +md_analyze_permissive_autolink_segment(MD_CTX* ctx, OFF off, OFF end, OFF* p_end, + int scan_backwards, MD_CHAR component_delim, const MD_CHAR* word_extra, + const MD_CHAR* word_delims, MD_MARK** p_cursor) +{ + int n_components = 0; + int n_open_brackets = 0; + int seen_word_delim = true; + int seen_component_delim = true; + OFF component_beg = off; + + if(word_extra == NULL) + word_extra = _T(""); + if(word_delims == NULL) + word_delims = _T(""); + + while(off != end) { + if(scan_backwards) + off--; + + /* Only accept extra and delimiter characters if they're not part of a + * resolved mark. */ + if(!ISALNUM(off) && !ISWHITESPACE(off)) { + if((!scan_backwards && md_scan_right_for_resolved_mark(ctx, *p_cursor, off, p_cursor) != NULL) || + (scan_backwards && md_scan_left_for_resolved_mark(ctx, *p_cursor, off, p_cursor) != NULL)) { + if(scan_backwards) + off++; + break; + } + } + + /* The autolink can be _inside_ brackets so we disallow unbalanced bracket pairs in the URL. + * (Note the brackets are not allowed in e-mail username, so we happily skip this in that case.) */ + if(!scan_backwards) { + if(CH(off) == _T('(')) { + n_open_brackets++; + } else if(CH(off) == _T(')')) { + if(n_open_brackets <= 0) + break; + n_open_brackets--; + } + } + + if(ISALNUM(off) || ISANYOF(off, word_extra)) { + seen_word_delim = false; + seen_component_delim = false; + } else { + if(seen_word_delim) + break; + + if(ISANYOF(off, word_delims)) { + seen_word_delim = true; + } else if(component_delim != _T('\0') && CH(off) == component_delim) { + if(seen_component_delim) + break; + seen_component_delim = true; + component_beg = off; + n_components++; + } else { + if(scan_backwards) + off++; + break; + } + } + + if(!scan_backwards) + off++; + } + + /* Rollback falsely consumed delimiter. */ + if(seen_word_delim || seen_component_delim) + off = (scan_backwards ? off+1 : off-1); + + if(off != component_beg) + n_components++; + + if(n_open_brackets != 0) + return -1; + + *p_end = off; + return n_components; +} + +static void +md_analyze_permissive_autolink(MD_CTX* ctx, int mark_index) +{ + MD_MARK* opener = &ctx->marks[mark_index]; + MD_MARK* closer = &ctx->marks[mark_index + 1]; /* The dummy. */ + OFF line_beg = closer->beg; /* md_collect_mark() sets this for us */ + OFF line_end = closer->end; /* ditto */ + OFF beg = opener->beg; + OFF end = opener->end; + MD_MARK* left_cursor = opener; + MD_MARK* right_cursor = opener; + + MD_ASSERT(closer->ch == 'D'); + + /* E-mail requires the user name (before '@', i.e. scanning backwards). */ + if(opener->ch == '@') { + MD_ASSERT(CH(opener->beg) == _T('@')); + if(md_analyze_permissive_autolink_segment(ctx, beg, line_beg, &beg, true, + _T('\0'), NULL, _T(".-_+"), &left_cursor) < 1) + return; + + /* Swallow optional "mailto:" or "xmpp:" before it. */ + if(beg >= 7 && md_ascii_eq(_T("mailto:"), STR(beg-7), 7)) + beg -= 7; + else if(beg >= 5 && md_ascii_eq(_T("xmpp:"), STR(beg-5), 5)) + beg -= 5; + else + opener->flags |= MD_MARK_AUTOLINK_MISSING_MAILTO; + } + + /* Verify there's line boundary, whitespace, allowed punctuation or + * resolved opener mark just before the suspected autolink. */ + if(beg > line_beg && !ISUNICODEWHITESPACEBEFORE(beg) && !ISANYOF(beg-1, _T("({["))) { + MD_MARK* mark; + + mark = md_scan_left_for_resolved_mark(ctx, left_cursor, beg-1, &left_cursor); + if(mark == NULL || !(mark->flags & MD_MARK_OPENER)) + return; + } + + /* Scan for hostname segment. Hostname is mandatory and requires at least two + * components delimited with a dot. */ + if(md_analyze_permissive_autolink_segment(ctx, end, line_end, &end, false, + _T('.'), NULL, _T("-_"), &right_cursor) < 2) + return; + + if(opener->ch != '@') { + /* Scan for path segment. */ + if(end < line_end && CH(end) == _T('/')) { + if(md_analyze_permissive_autolink_segment(ctx, end+1, line_end, &end, false, + _T('/'), _T(".+-_~%"), NULL, &right_cursor) < 0) + return; + + /* Path can also end with additional '/' if its a directory. */ + if(end < line_end && CH(end) == _T('/')) + end++; + } + + /* Scan for query segment. */ + if(end < line_end && CH(end) == _T('?')) { + if(md_analyze_permissive_autolink_segment(ctx, end+1, line_end, &end, false, + _T('&'), _T("._=()"), _T("+-"), &right_cursor) < 0) + return; + } + + /* Scan for fragment segment. */ + if(end < line_end && CH(end) == _T('#')) { + if(md_analyze_permissive_autolink_segment(ctx, end+1, line_end, &end, false, + _T('\0'), NULL, _T(".-+_"), &right_cursor) < 0) + return; + } + } + + /* Verify there's line boundary, whitespace, allowed punctuation or + * resolved closer mark just after the suspected autolink. */ + if(end < line_end && !ISUNICODEWHITESPACE(end) && !ISANYOF(end, _T(")}].!?,;"))) { + MD_MARK* mark; + + mark = md_scan_right_for_resolved_mark(ctx, right_cursor, end, &right_cursor); + if(mark == NULL || !(mark->flags & MD_MARK_CLOSER)) + return; + } + + /* Success, we are an autolink. */ + opener->beg = beg; + opener->end = beg; + closer->beg = end; + closer->end = end; + closer->ch = opener->ch; + md_resolve_range(ctx, mark_index, mark_index + 1); +} + +#define MD_ANALYZE_NOSKIP_EMPH 0x01 + +static inline void +md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, + int mark_beg, int mark_end, const CHAR* mark_chars, const CHAR* noskip_mark_chars) +{ + int i = mark_beg; + OFF last_end = lines[0].beg; + + MD_UNUSED(lines); + MD_UNUSED(n_lines); + + while(i < mark_end) { + MD_MARK* mark = &ctx->marks[i]; + + /* Skip resolved spans. */ + if(mark->flags & MD_MARK_RESOLVED) { + if((mark->flags & MD_MARK_OPENER) && + (noskip_mark_chars == NULL || !(ISANYOF_(mark->ch, noskip_mark_chars)))) + { + MD_ASSERT(i < mark->next); + i = mark->next + 1; + } else { + i++; + } + continue; + } + + /* Skip marks we do not want to deal with. */ + if(!ISANYOF_(mark->ch, mark_chars)) { + i++; + continue; + } + + /* The resolving in previous step could have expanded a mark. */ + if(mark->beg < last_end) { + i++; + continue; + } + + /* Analyze the mark. */ + switch(mark->ch) { + case '[': MD_FALLTHROUGH(); + case '!': MD_FALLTHROUGH(); + case ']': md_analyze_bracket(ctx, i); break; + case '&': md_analyze_entity(ctx, i); break; + case '_': MD_FALLTHROUGH(); + case '*': md_analyze_emph(ctx, i); break; + case '~': md_analyze_tilde(ctx, i); break; + case '^': md_analyze_caret(ctx, i); break; + case '$': md_analyze_dollar(ctx, i); break; + case '.': MD_FALLTHROUGH(); + case ':': MD_FALLTHROUGH(); + case '@': md_analyze_permissive_autolink(ctx, i); break; + case '|': md_analyze_spoiler(ctx, i); break; + case '=': md_analyze_highlight(ctx, i); break; + case '+': md_analyze_insert(ctx, i); break; + } + + if(mark->flags & MD_MARK_RESOLVED) { + if(mark->flags & MD_MARK_OPENER) + last_end = ctx->marks[mark->next].end; + else + last_end = mark->end; + } + + i++; + } +} + +/* Analyze marks (build ctx->marks). */ +static int +md_analyze_inlines(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int table_mode) +{ + int i; + int ret; + + /* Reset the previously collected stack of marks. */ + ctx->n_marks = 0; + + /* Collect all marks. */ + MD_CHECK(md_collect_marks(ctx, lines, n_lines, table_mode)); + + /* (1) Bracket spans: links, wiki links, footnotes. */ + md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("[]!"), NULL); + MD_CHECK(md_resolve_brackets(ctx, lines, n_lines)); + BRACKET_OPENERS.top = -1; + ctx->unresolved_link_head = -1; + ctx->unresolved_link_tail = -1; + + if(table_mode) { + /* (2) Analyze table cell boundaries. */ + MD_ASSERT(n_lines == 1); + ctx->n_table_cell_boundaries = 0; + for(i = 0; i < ctx->n_marks; i++) { + if(!(ctx->marks[i].flags & MD_MARK_RESOLVED) && ctx->marks[i].ch == '|') + md_analyze_table_cell_boundary(ctx, i); + } + return ret; + } + + /* (3) Emphasis and strong emphasis; permissive autolinks. */ + md_analyze_link_contents(ctx, lines, n_lines, 0, ctx->n_marks); + +abort: + return ret; +} + +static void +md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, + int mark_beg, int mark_end) +{ + int i; + CHAR emph_mark_types[16]; + SZ n_emph_mark_types = 0; + + emph_mark_types[n_emph_mark_types++] = _T('&'); + emph_mark_types[n_emph_mark_types++] = _T('*'); + emph_mark_types[n_emph_mark_types++] = _T('_'); + if(ctx->parser.flags & MD_FLAG_LATEXMATHSPANS) + emph_mark_types[n_emph_mark_types++] = _T('$'); + if(ctx->parser.flags & MD_FLAG_HIGHLIGHT) + emph_mark_types[n_emph_mark_types++] = _T('='); + if(ctx->parser.flags & MD_FLAG_INSERT) + emph_mark_types[n_emph_mark_types++] = _T('+'); + if(ctx->parser.flags & MD_FLAG_SPOILERS) + emph_mark_types[n_emph_mark_types++] = _T('|'); + if(ctx->parser.flags & MD_FLAG_SUPERSCRIPTS) + emph_mark_types[n_emph_mark_types++] = _T('^'); + if((ctx->parser.flags & MD_FLAG_STRIKETHROUGH) || (ctx->parser.flags & MD_FLAG_SUBSCRIPTS)) + emph_mark_types[n_emph_mark_types++] = _T('~'); + emph_mark_types[n_emph_mark_types] = _T('\0'); + md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, emph_mark_types, NULL); + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEAUTOLINKS) { + /* These have to be processed last, as they may be greedy and expand + * from their original mark. Also their implementation must be careful + * not to cross any (previously) resolved marks when doing so. */ + CHAR autolink_mark_types[16]; + SZ n_autolink_mark_types = 0; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEEMAILAUTOLINKS) + autolink_mark_types[n_autolink_mark_types++] = _T('@'); + if(ctx->parser.flags & MD_FLAG_PERMISSIVEURLAUTOLINKS) + autolink_mark_types[n_autolink_mark_types++] = _T(':'); + if(ctx->parser.flags & MD_FLAG_PERMISSIVEWWWAUTOLINKS) + autolink_mark_types[n_autolink_mark_types++] = _T('.'); + autolink_mark_types[n_autolink_mark_types] = _T('\0'); + md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, autolink_mark_types, emph_mark_types); + } + + for(i = 0; i < (int) SIZEOF_ARRAY(ctx->opener_stacks); i++) + ctx->opener_stacks[i].top = -1; +} + +static int +md_enter_leave_span_a(MD_CTX* ctx, int enter, MD_SPANTYPE type, + const CHAR* dest, SZ dest_size, int is_autolink, + const CHAR* title, SZ title_size) +{ + MD_ATTRIBUTE_BUILD href_build = { 0 }; + MD_ATTRIBUTE_BUILD title_build = { 0 }; + MD_SPAN_A_DETAIL det; + int ret = 0; + + /* Note we here rely on fact that MD_SPAN_A_DETAIL and + * MD_SPAN_IMG_DETAIL are binary-compatible. */ + memset(&det, 0, sizeof(MD_SPAN_A_DETAIL)); + MD_CHECK(md_build_attribute(ctx, dest, dest_size, + (is_autolink ? MD_BUILD_ATTR_NO_ESCAPES : 0), + &det.href, &href_build)); + MD_CHECK(md_build_attribute(ctx, title, title_size, 0, &det.title, &title_build)); + det.is_autolink = is_autolink; + if(enter) + MD_ENTER_SPAN(type, &det); + else + MD_LEAVE_SPAN(type, &det); + +abort: + md_free_attribute(ctx, &href_build); + md_free_attribute(ctx, &title_build); + return ret; +} + +static int +md_enter_leave_span_wikilink(MD_CTX* ctx, int enter, const CHAR* target, SZ target_size) +{ + MD_ATTRIBUTE_BUILD target_build = { 0 }; + MD_SPAN_WIKILINK_DETAIL det; + int ret = 0; + + memset(&det, 0, sizeof(MD_SPAN_WIKILINK_DETAIL)); + MD_CHECK(md_build_attribute(ctx, target, target_size, 0, &det.target, &target_build)); + + if (enter) + MD_ENTER_SPAN(MD_SPAN_WIKILINK, &det); + else + MD_LEAVE_SPAN(MD_SPAN_WIKILINK, &det); + +abort: + md_free_attribute(ctx, &target_build); + return ret; +} + +static int +md_enter_leave_span_footnote_ref(MD_CTX* ctx, unsigned int id, + unsigned int ref_id, const CHAR* label, SZ label_size) +{ + MD_ATTRIBUTE_BUILD label_build = { 0 }; + MD_SPAN_FOOTNOTE_REF_DETAIL det; + int ret = 0; + + memset(&det, 0, sizeof(MD_SPAN_FOOTNOTE_REF_DETAIL)); + det.id = id; + det.ref_id = ref_id; + MD_CHECK(md_build_attribute(ctx, label, label_size, 0, + &det.label, &label_build)); + + MD_ENTER_SPAN(MD_SPAN_FOOTNOTE_REF, &det); + MD_LEAVE_SPAN(MD_SPAN_FOOTNOTE_REF, &det); + +abort: + md_free_attribute(ctx, &label_build); + return ret; +} + + +/* Render the output, accordingly to the analyzed ctx->marks. */ +static int +md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) +{ + MD_TEXTTYPE text_type; + const MD_LINE* line = lines; + MD_MARK* prev_mark = NULL; + MD_MARK* mark; + OFF off = lines[0].beg; + OFF end = lines[n_lines-1].end; + OFF tmp; + int enforce_hardbreak = 0; + int ret = 0; + + /* Find first resolved mark. Note there is always at least one resolved + * mark, the dummy last one after the end of the latest line we actually + * never really reach. This saves us of a lot of special checks and cases + * in this function. */ + mark = ctx->marks; + while(!(mark->flags & MD_MARK_RESOLVED)) + mark++; + + text_type = MD_TEXT_NORMAL; + + while(1) { + /* Process the text up to the next mark or end-of-line. */ + tmp = (line->end < mark->beg ? line->end : mark->beg); + if(tmp > off) { + MD_TEXT(text_type, STR(off), tmp - off); + off = tmp; + } + + /* If reached the mark, process it and move to next one. */ + if(off >= mark->beg) { + switch(mark->ch) { + case '\\': /* Backslash escape. */ + if(ISNEWLINE(mark->beg+1)) + enforce_hardbreak = 1; + else + MD_TEXT(text_type, STR(mark->beg+1), 1); + break; + + case ' ': /* Non-trivial space. */ + MD_TEXT(text_type, _T(" "), 1); + break; + + case '`': /* Code span. */ + if(mark->flags & MD_MARK_OPENER) { + MD_ENTER_SPAN(MD_SPAN_CODE, NULL); + text_type = MD_TEXT_CODE; + } else { + MD_LEAVE_SPAN(MD_SPAN_CODE, NULL); + text_type = MD_TEXT_NORMAL; + } + break; + + case '_': /* Underline (or emphasis if we fall through). */ + if(ctx->parser.flags & MD_FLAG_UNDERLINE) { + if(mark->flags & MD_MARK_OPENER) { + while(off < mark->end) { + MD_ENTER_SPAN(MD_SPAN_U, NULL); + off++; + } + } else { + while(off < mark->end) { + MD_LEAVE_SPAN(MD_SPAN_U, NULL); + off++; + } + } + break; + } + MD_FALLTHROUGH(); + + case '*': /* Emphasis, strong emphasis. */ + if(mark->flags & MD_MARK_OPENER) { + if((mark->end - off) % 2) { + MD_ENTER_SPAN(MD_SPAN_EM, NULL); + off++; + } + while(off + 1 < mark->end) { + MD_ENTER_SPAN(MD_SPAN_STRONG, NULL); + off += 2; + } + } else { + while(off + 1 < mark->end) { + MD_LEAVE_SPAN(MD_SPAN_STRONG, NULL); + off += 2; + } + if((mark->end - off) % 2) { + MD_LEAVE_SPAN(MD_SPAN_EM, NULL); + off++; + } + } + break; + + case '~': + if(mark->end - mark->beg == 1 && (ctx->parser.flags & MD_FLAG_SUBSCRIPTS)) { + if(mark->flags & MD_MARK_OPENER) + MD_ENTER_SPAN(MD_SPAN_SUBSCRIPT, NULL); + else + MD_LEAVE_SPAN(MD_SPAN_SUBSCRIPT, NULL); + } else { + if(mark->flags & MD_MARK_OPENER) + MD_ENTER_SPAN(MD_SPAN_DEL, NULL); + else + MD_LEAVE_SPAN(MD_SPAN_DEL, NULL); + } + break; + + case '^': + if(mark->flags & MD_MARK_OPENER) + MD_ENTER_SPAN(MD_SPAN_SUPERSCRIPT, NULL); + else + MD_LEAVE_SPAN(MD_SPAN_SUPERSCRIPT, NULL); + break; + + case '|': + if(mark->end - mark->beg == 2) { + if(mark->flags & MD_MARK_OPENER) + MD_ENTER_SPAN(MD_SPAN_SPOILER, NULL); + else + MD_LEAVE_SPAN(MD_SPAN_SPOILER, NULL); + } + break; + + case '=': + if(mark->end - mark->beg == 2) { + if(mark->flags & MD_MARK_OPENER) + MD_ENTER_SPAN(MD_SPAN_MARK, NULL); + else + MD_LEAVE_SPAN(MD_SPAN_MARK, NULL); + } + break; + + case '+': + if(mark->end - mark->beg == 2) { + if(mark->flags & MD_MARK_OPENER) + MD_ENTER_SPAN(MD_SPAN_INS, NULL); + else + MD_LEAVE_SPAN(MD_SPAN_INS, NULL); + } + break; + + case '$': + if(mark->flags & MD_MARK_OPENER) { + MD_ENTER_SPAN((mark->end - off) % 2 ? MD_SPAN_LATEXMATH : MD_SPAN_LATEXMATH_DISPLAY, NULL); + text_type = MD_TEXT_LATEXMATH; + } else { + MD_LEAVE_SPAN((mark->end - off) % 2 ? MD_SPAN_LATEXMATH : MD_SPAN_LATEXMATH_DISPLAY, NULL); + text_type = MD_TEXT_NORMAL; + } + break; + + case '[': /* Footnote reference, link, wiki link, or image. */ + case '!': + case ']': + { + const MD_MARK* opener = (mark->ch != ']' ? mark : &ctx->marks[mark->prev]); + const MD_MARK* closer = &ctx->marks[opener->next]; + const MD_MARK* dest_mark; + const MD_MARK* title_mark; + + /* Footnote reference: self-contained span, no text emitted. + * Only the opener is ever processed here; the closer mark + * is guaranteed to be skipped by the off-advance below. */ + if(opener->flags & MD_MARK_BRACKET_FOOTNOTEREF) { + MD_MARK* index_mark = (MD_MARK*) opener + 1; + MD_ASSERT(mark->ch != ']'); + MD_ASSERT(index_mark->ch == 'D'); + MD_CHECK(md_enter_leave_span_footnote_ref(ctx, + (unsigned int) index_mark->beg, + (unsigned int) index_mark->end, + STR(opener->end), closer->beg - opener->end)); + /* Redirect the opener's end past the whole [^label] + * so that the post-switch "off = mark->end" skips + * the label text and the closing ]. */ + ((MD_MARK*) mark)->end = closer->end; + break; + } + + if ((opener->ch == '[' && closer->ch == ']') && + opener->end - opener->beg >= 2 && + closer->end - closer->beg >= 2) + { + int has_label = (opener->end - opener->beg > 2); + SZ target_sz; + + if(has_label) + target_sz = opener->end - (opener->beg+2); + else + target_sz = closer->beg - opener->end; + + MD_CHECK(md_enter_leave_span_wikilink(ctx, (mark->ch != ']'), + has_label ? STR(opener->beg+2) : STR(opener->end), + target_sz)); + + break; + } + + dest_mark = opener+1; + MD_ASSERT(dest_mark->ch == 'D'); + title_mark = opener+2; + MD_ASSERT(title_mark->ch == 'D'); + + MD_CHECK(md_enter_leave_span_a(ctx, (mark->ch != ']'), + (opener->ch == '!' ? MD_SPAN_IMG : MD_SPAN_A), + STR(dest_mark->beg), dest_mark->end - dest_mark->beg, false, + md_mark_get_ptr(ctx, (int)(title_mark - ctx->marks)), + title_mark->prev)); + + /* link/image closer may span multiple lines. */ + if(mark->ch == ']') { + while(mark->end > line->end) + line++; + } + + break; + } + + case '<': + case '>': /* Autolink or raw HTML. */ + if(!(mark->flags & MD_MARK_AUTOLINK)) { + /* Raw HTML. */ + if(mark->flags & MD_MARK_OPENER) + text_type = MD_TEXT_HTML; + else + text_type = MD_TEXT_NORMAL; + break; + } + /* Pass through, if auto-link. */ + MD_FALLTHROUGH(); + + case '@': /* Permissive e-mail autolink. */ + case ':': /* Permissive URL autolink. */ + case '.': /* Permissive WWW autolink. */ + { + MD_MARK* opener = ((mark->flags & MD_MARK_OPENER) ? mark : &ctx->marks[mark->prev]); + MD_MARK* closer = &ctx->marks[opener->next]; + const CHAR* dest = STR(opener->end); + SZ dest_size = closer->beg - opener->end; + + /* For permissive auto-links we do not know closer mark + * position at the time of md_collect_marks(), therefore + * it can be out-of-order in ctx->marks[]. + * + * With this flag, we make sure that we output the closer + * only if we processed the opener. */ + if(mark->flags & MD_MARK_OPENER) + closer->flags |= MD_MARK_VALIDPERMISSIVEAUTOLINK; + + if(opener->ch == '.' || + (ISANYOF2_(opener->ch, _T('@'), _T('<')) && (opener->flags & MD_MARK_AUTOLINK_MISSING_MAILTO))) + { + dest_size += 7; + MD_TEMP_BUFFER(dest_size * sizeof(CHAR)); + memcpy(ctx->buffer, + (opener->ch == '.' ? _T("http://") : _T("mailto:")), + 7 * sizeof(CHAR)); + memcpy(ctx->buffer + 7, dest, (dest_size-7) * sizeof(CHAR)); + dest = ctx->buffer; + } + + if(closer->flags & MD_MARK_VALIDPERMISSIVEAUTOLINK) + MD_CHECK(md_enter_leave_span_a(ctx, (mark->flags & MD_MARK_OPENER), + MD_SPAN_A, dest, dest_size, true, NULL, 0)); + break; + } + + case '&': /* Entity. */ + MD_TEXT(MD_TEXT_ENTITY, STR(mark->beg), mark->end - mark->beg); + break; + + case '\0': + MD_TEXT(MD_TEXT_NULLCHAR, _T(""), 1); + break; + + case 127: + goto abort; + } + + off = mark->end; + + /* Move to next resolved mark. */ + prev_mark = mark; + mark++; + while(!(mark->flags & MD_MARK_RESOLVED) || mark->beg < off) + mark++; + } + + /* If reached end of line, move to next one. */ + if(off >= line->end) { + /* If it is the last line, we are done. */ + if(off >= end) + break; + + if(text_type == MD_TEXT_CODE || text_type == MD_TEXT_LATEXMATH) { + MD_ASSERT(prev_mark != NULL); + MD_ASSERT(ISANYOF2_(prev_mark->ch, '`', '$') && (prev_mark->flags & MD_MARK_OPENER)); + MD_ASSERT(ISANYOF2_(mark->ch, '`', '$') && (mark->flags & MD_MARK_CLOSER)); + + /* Inside a code span, trailing line whitespace has to be + * outputted. */ + tmp = off; + while(off < ctx->size && ISBLANK(off)) + off++; + if(off > tmp) + MD_TEXT(text_type, STR(tmp), off-tmp); + + /* and new lines are transformed into single spaces. Emit the + * space when off rests on an interior newline still preceding + * the closer. Testing off == line->end here instead drops the + * space when the line ends in whitespace, because the loop + * above advances off past line->end over the trailing blanks + * (CommonMark code-span examples 335, 337, 640). */ + if(off < mark->beg && ISNEWLINE(off)) + MD_TEXT(text_type, _T(" "), 1); + } else if(text_type == MD_TEXT_HTML) { + /* Inside raw HTML, we output the new line verbatim, including + * any trailing spaces. */ + tmp = off; + while(tmp < end && ISBLANK(tmp)) + tmp++; + if(tmp > off) + MD_TEXT(MD_TEXT_HTML, STR(off), tmp - off); + MD_TEXT(MD_TEXT_HTML, _T("\n"), 1); + } else { + /* Output soft or hard line break. */ + MD_TEXTTYPE break_type = MD_TEXT_SOFTBR; + + if(text_type == MD_TEXT_NORMAL) { + if(enforce_hardbreak || (ctx->parser.flags & MD_FLAG_HARD_SOFT_BREAKS)) { + break_type = MD_TEXT_BR; + } else { + while(off < ctx->size && ISBLANK(off)) + off++; + if(off >= line->end + 2 && CH(off-2) == _T(' ') && CH(off-1) == _T(' ') && ISNEWLINE(off)) + break_type = MD_TEXT_BR; + } + } + + MD_TEXT(break_type, _T("\n"), 1); + } + + /* Move to the next line. */ + line++; + off = MAX(off, line->beg); + + enforce_hardbreak = 0; + } + } + +abort: + return ret; +} + + +/*************************** + *** Processing Tables *** + ***************************/ + +static void +md_analyze_table_alignment(MD_CTX* ctx, OFF beg, OFF end, MD_ALIGN* align, int n_align) +{ + static const MD_ALIGN align_map[] = { MD_ALIGN_DEFAULT, MD_ALIGN_LEFT, MD_ALIGN_RIGHT, MD_ALIGN_CENTER }; + OFF off = beg; + + while(n_align > 0) { + int index = 0; /* index into align_map[] */ + + while(off < end && CH(off) != _T('-')) + off++; + if(off > beg && CH(off-1) == _T(':')) + index |= 1; + while(off < end && CH(off) == _T('-')) + off++; + if(off < end && CH(off) == _T(':')) + index |= 2; + + *align = align_map[index]; + align++; + n_align--; + } + +} + +/* Forward declaration. */ +static int md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines); + +static int +md_process_table_cell(MD_CTX* ctx, MD_BLOCKTYPE cell_type, MD_ALIGN align, OFF beg, OFF end) +{ + MD_LINE line; + MD_BLOCK_TD_DETAIL det; + int ret = 0; + + while(beg < end && ISWHITESPACE(beg)) + beg++; + while(end > beg && ISWHITESPACE(end-1)) + end--; + + det.align = align; + line.beg = beg; + line.end = end; + + MD_ENTER_BLOCK(cell_type, &det); + MD_CHECK(md_process_normal_block_contents(ctx, &line, 1)); + MD_LEAVE_BLOCK(cell_type, &det); + +abort: + return ret; +} + +static int +md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end, + const MD_ALIGN* align, int col_count) +{ + MD_LINE line; + OFF* cell_begs = NULL; + int i, j, k, n; + int ret = 0; + MD_MARK* mark = NULL; + + line.beg = beg; + line.end = end; + + /* Break the line into table cells by identifying pipe characters who + * form the cell boundary. */ + MD_CHECK(md_analyze_inlines(ctx, &line, 1, true)); + + /* We have to remember the cell boundaries in local buffer because + * ctx->marks[] shall be reused during cell contents processing. */ + n = ctx->n_table_cell_boundaries + 2; + cell_begs = (OFF*) malloc(n * sizeof(OFF)); + if(cell_begs == NULL) { + MD_LOG("malloc() failed."); + ret = -1; + goto abort; + } + j = 0; + + /* First cell of the row may or may not be started with '|'. */ + if(ctx->table_cell_boundaries_head < 0 || + ctx->marks[ctx->table_cell_boundaries_head].beg > beg) + cell_begs[j++] = beg; + for(i = ctx->table_cell_boundaries_head; i >= 0; i = ctx->marks[i].next) { + mark = &ctx->marks[i]; + for(k = 0; k < (int)(mark->end - mark->beg); k++) + cell_begs[j++] = mark->beg + k + 1; + } + if(mark == NULL || mark->end < end) + cell_begs[j++] = end+1; + + /* Process cells. */ + MD_ENTER_BLOCK(MD_BLOCK_TR, NULL); + for(i = 0; i < j-1 && i < col_count; i++) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[i], cell_begs[i], cell_begs[i+1]-1)); + /* Make sure we report enough table cells even if the current table contains + * too few of them. */ + while(i < col_count) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[i++], 0, 0)); + MD_LEAVE_BLOCK(MD_BLOCK_TR, NULL); + +abort: + free(cell_begs); + + ctx->table_cell_boundaries_head = -1; + ctx->table_cell_boundaries_tail = -1; + + return ret; +} + +static int +md_process_table_block_contents(MD_CTX* ctx, int col_count, const MD_LINE* lines, MD_SIZE n_lines) +{ + MD_ALIGN* align; + MD_SIZE line_index; + int ret = 0; + + /* At least two lines have to be present: The column headers and the line + * with the underlines. */ + MD_ASSERT(n_lines >= 2); + + align = malloc(col_count * sizeof(MD_ALIGN)); + if(align == NULL) { + MD_LOG("malloc() failed."); + ret = -1; + goto abort; + } + + md_analyze_table_alignment(ctx, lines[1].beg, lines[1].end, align, col_count); + + MD_ENTER_BLOCK(MD_BLOCK_THEAD, NULL); + MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TH, + lines[0].beg, lines[0].end, align, col_count)); + MD_LEAVE_BLOCK(MD_BLOCK_THEAD, NULL); + + if(n_lines > 2) { + MD_ENTER_BLOCK(MD_BLOCK_TBODY, NULL); + for(line_index = 2; line_index < n_lines; line_index++) { + MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TD, + lines[line_index].beg, lines[line_index].end, align, col_count)); + } + MD_LEAVE_BLOCK(MD_BLOCK_TBODY, NULL); + } + +abort: + free(align); + return ret; +} + + +/************************** + *** Processing Block *** + **************************/ + +#define MD_BLOCK_CONTAINER_OPENER 0x01 +#define MD_BLOCK_CONTAINER_CLOSER 0x02 +#define MD_BLOCK_CONTAINER (MD_BLOCK_CONTAINER_OPENER | MD_BLOCK_CONTAINER_CLOSER) +#define MD_BLOCK_LOOSE_LIST 0x04 +#define MD_BLOCK_SETEXT_HEADER 0x08 + +struct MD_BLOCK_tag { + MD_BLOCKTYPE type : 8; + unsigned flags : 8; + + /* MD_BLOCK_H: Header level (1 - 6) + * MD_BLOCK_CODE: Non-zero if fenced, zero if indented. + * MD_BLOCK_LI: Task mark character (0 if not task list item, 'x', 'X' or ' '). + * MD_BLOCK_TABLE: Column count (as determined by the table underline). + * MD_BLOCK_ADMONITION: Admonition type. + */ + unsigned data : 16; + + /* Leaf blocks: Count of lines (MD_LINE or MD_VERBATIMLINE) on the block. + * MD_BLOCK_LI: Task mark offset in the input doc. + * MD_BLOCK_OL: Start item number. + */ + MD_SIZE n_lines; +}; + +struct MD_CONTAINER_tag { + CHAR ch; + unsigned is_loose : 1; + unsigned is_task : 1; + unsigned is_admonition : 1; + unsigned admonition_type : 3; + unsigned start; + unsigned mark_indent; + unsigned contents_indent; + OFF block_byte_off; + OFF task_mark_off; +}; + + +static int +md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) +{ + int i; + int ret; + + MD_CHECK(md_analyze_inlines(ctx, lines, n_lines, false)); + MD_CHECK(md_process_inlines(ctx, lines, n_lines)); + +abort: + /* Free any temporary memory blocks stored within some dummy marks. */ + for(i = ctx->ptr_stack.top; i >= 0; i = ctx->marks[i].next) + free(md_mark_get_ptr(ctx, i)); + ctx->ptr_stack.top = -1; + + return ret; +} + +static int +md_process_verbatim_block_contents(MD_CTX* ctx, MD_TEXTTYPE text_type, const MD_VERBATIMLINE* lines, MD_SIZE n_lines) +{ + static const CHAR indent_chunk_str[] = _T(" "); + static const SZ indent_chunk_size = SIZEOF_ARRAY(indent_chunk_str) - 1; + + MD_SIZE line_index; + int ret = 0; + + for(line_index = 0; line_index < n_lines; line_index++) { + const MD_VERBATIMLINE* line = &lines[line_index]; + int indent = line->indent; + + MD_ASSERT(indent >= 0); + + /* Output code indentation. */ + while(indent > (int) indent_chunk_size) { + MD_TEXT(text_type, indent_chunk_str, indent_chunk_size); + indent -= indent_chunk_size; + } + if(indent > 0) + MD_TEXT(text_type, indent_chunk_str, indent); + + /* Output the code line itself. */ + MD_TEXT_INSECURE(text_type, STR(line->beg), line->end - line->beg); + + /* Enforce end-of-line. */ + MD_TEXT(text_type, _T("\n"), 1); + } + +abort: + return ret; +} + +static int +md_process_code_block_contents(MD_CTX* ctx, int is_fenced, const MD_VERBATIMLINE* lines, MD_SIZE n_lines) +{ + if(is_fenced) { + /* Skip the first line in case of fenced code: It is the fence. + * (Only the starting fence is present due to logic in md_analyze_line().) */ + lines++; + n_lines--; + } else { + /* Ignore blank lines at start/end of indented code block. */ + while(n_lines > 0 && lines[0].beg == lines[0].end) { + lines++; + n_lines--; + } + while(n_lines > 0 && lines[n_lines-1].beg == lines[n_lines-1].end) { + n_lines--; + } + } + + if(n_lines == 0) + return 0; + + return md_process_verbatim_block_contents(ctx, MD_TEXT_CODE, lines, n_lines); +} + +static int +md_setup_fenced_code_detail(MD_CTX* ctx, const MD_BLOCK* block, MD_BLOCK_CODE_DETAIL* det, + MD_ATTRIBUTE_BUILD* info_build, MD_ATTRIBUTE_BUILD* lang_build) +{ + const MD_VERBATIMLINE* fence_line = (const MD_VERBATIMLINE*)(block + 1); + OFF beg = fence_line->beg; + OFF end = fence_line->end; + OFF lang_end; + CHAR fence_ch = CH(fence_line->beg); + int ret = 0; + + /* Skip the fence itself. */ + while(beg < ctx->size && CH(beg) == fence_ch) + beg++; + /* Trim initial spaces. */ + while(beg < ctx->size && CH(beg) == _T(' ')) + beg++; + + /* Trim trailing spaces. */ + while(end > beg && CH(end-1) == _T(' ')) + end--; + + /* Build info string attribute. */ + MD_CHECK(md_build_attribute(ctx, STR(beg), end - beg, 0, &det->info, info_build)); + + /* Build info string attribute. */ + lang_end = beg; + while(lang_end < end && !ISWHITESPACE(lang_end)) + lang_end++; + MD_CHECK(md_build_attribute(ctx, STR(beg), lang_end - beg, 0, &det->lang, lang_build)); + + det->fence_char = fence_ch; + +abort: + return ret; +} + +static int +md_process_leaf_block(MD_CTX* ctx, MD_BLOCK* block) +{ + union { + MD_BLOCK_H_DETAIL header; + MD_BLOCK_CODE_DETAIL code; + MD_BLOCK_TABLE_DETAIL table; + MD_BLOCK_BLANK_DETAIL blank; + } det; + MD_ATTRIBUTE_BUILD info_build = { 0 }; + MD_ATTRIBUTE_BUILD lang_build = { 0 }; + int is_in_tight_list; + int clean_fence_code_detail = false; + int ret = 0; + + /* For large tables check the table density: If it's too low, lets suppress + * its interpretation as a table, as a safety measure against quadratic + * output size explosion. See https://github.com/mity/md4c/issues/345 */ + if(block->type == MD_BLOCK_TABLE) { + unsigned n_cols = block->data; + unsigned n_rows = block->n_lines; + + if(n_cols > 32 && n_rows > 4096 / n_cols) { + const MD_LINE* lines = (const MD_LINE*)(block + 1); + SZ table_input_size = n_rows; + unsigned i; + + for(i = 0; i < n_rows; i++) + table_input_size += lines[i].end - lines[i].beg; + + if(table_input_size / n_cols < n_rows / 4) { + /* Number of characters encoding the table in the input is + * lower then 25% of all cells to be generated? */ + MD_LOG("Suppressing too sparse table " + "(see https://github.com/mity/md4c/issues/345)"); + block->type = MD_BLOCK_P; + } + } + } + + memset(&det, 0, sizeof(det)); + + if(ctx->n_containers == 0) + is_in_tight_list = false; + else + is_in_tight_list = !ctx->containers[ctx->n_containers-1].is_loose; + + switch(block->type) { + case MD_BLOCK_H: + det.header.level = block->data; + break; + + case MD_BLOCK_CODE: + /* For fenced code block, we may need to set the info string. */ + if(block->data != 0) { + memset(&det.code, 0, sizeof(MD_BLOCK_CODE_DETAIL)); + clean_fence_code_detail = true; + MD_CHECK(md_setup_fenced_code_detail(ctx, block, &det.code, &info_build, &lang_build)); + } + break; + + case MD_BLOCK_TABLE: + det.table.col_count = block->data; + det.table.head_row_count = 1; + det.table.body_row_count = block->n_lines - 2; + break; + + case MD_BLOCK_BLANK: + det.blank.line_count = block->data; + break; + + default: + /* Noop. */ + break; + } + + if(!is_in_tight_list || block->type != MD_BLOCK_P) + MD_ENTER_BLOCK(block->type, (void*) &det); + + /* Process the block contents accordingly to is type. */ + switch(block->type) { + case MD_BLOCK_HR: + case MD_BLOCK_BLANK: + /* noop (no contents) */ + break; + + case MD_BLOCK_CODE: + MD_CHECK(md_process_code_block_contents(ctx, (block->data != 0), + (const MD_VERBATIMLINE*)(block + 1), block->n_lines)); + break; + + case MD_BLOCK_HTML: + MD_CHECK(md_process_verbatim_block_contents(ctx, MD_TEXT_HTML, + (const MD_VERBATIMLINE*)(block + 1), block->n_lines)); + break; + + case MD_BLOCK_TABLE: + MD_CHECK(md_process_table_block_contents(ctx, block->data, + (const MD_LINE*)(block + 1), block->n_lines)); + break; + + default: + MD_CHECK(md_process_normal_block_contents(ctx, + (const MD_LINE*)(block + 1), block->n_lines)); + break; + } + + if(!is_in_tight_list || block->type != MD_BLOCK_P) + MD_LEAVE_BLOCK(block->type, (void*) &det); + +abort: + if(clean_fence_code_detail) { + md_free_attribute(ctx, &info_build); + md_free_attribute(ctx, &lang_build); + } + return ret; +} + +static const MD_CHAR* MD_ADMONITION_TAGS[] = { _T("note"), _T("tip"), _T("important"), _T("warning"), _T("caution") }; + +static int +md_process_all_blocks(MD_CTX* ctx) +{ + MD_TEXTTYPE adm_substr_types[1] = { MD_TEXT_NORMAL }; + MD_OFFSET adm_substr_offsets[2]; + int byte_off = 0; + int ret = 0; + + /* ctx->containers now is not needed for detection of lists and list items + * so we reuse it for tracking what lists are loose or tight. We rely + * on the fact the vector is large enough to hold the deepest nesting + * level of lists. */ + ctx->n_containers = 0; + + while(byte_off < ctx->n_block_bytes) { + MD_BLOCK* block = (MD_BLOCK*)((char*)ctx->block_bytes + byte_off); + union { + MD_BLOCK_UL_DETAIL ul; + MD_BLOCK_OL_DETAIL ol; + MD_BLOCK_LI_DETAIL li; + MD_BLOCK_ADMONITION_DETAIL adm; + } det; + + switch(block->type) { + case MD_BLOCK_UL: + det.ul.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? false : true; + det.ul.mark = (CHAR) block->data; + break; + + case MD_BLOCK_OL: + det.ol.start = block->n_lines; + det.ol.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? false : true; + det.ol.mark_delimiter = (CHAR) block->data; + break; + + case MD_BLOCK_LI: + det.li.is_task = (block->data != 0); + det.li.task_mark = (CHAR) block->data; + det.li.task_mark_offset = (OFF) block->n_lines; + break; + + case MD_BLOCK_ADMONITION: + adm_substr_offsets[0] = 0; + adm_substr_offsets[1] = (unsigned) md_strlen(MD_ADMONITION_TAGS[block->data]); + + det.adm.type.text = MD_ADMONITION_TAGS[block->data]; + det.adm.type.size = adm_substr_offsets[1]; + det.adm.type.substr_types = adm_substr_types; + det.adm.type.substr_offsets = adm_substr_offsets; + break; + + default: + /* noop */ + break; + } + + if(block->flags & MD_BLOCK_CONTAINER) { + if(block->flags & MD_BLOCK_CONTAINER_CLOSER) { + MD_LEAVE_BLOCK(block->type, &det); + + if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL || + block->type == MD_BLOCK_QUOTE || block->type == MD_BLOCK_ADMONITION) + ctx->n_containers--; + } + + if(block->flags & MD_BLOCK_CONTAINER_OPENER) { + MD_ENTER_BLOCK(block->type, &det); + + if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL) { + ctx->containers[ctx->n_containers].is_loose = (block->flags & MD_BLOCK_LOOSE_LIST) ? true : false; + ctx->n_containers++; + } else if(block->type == MD_BLOCK_QUOTE || block->type == MD_BLOCK_ADMONITION) { + /* This causes that any text in a block quote, even if + * nested inside a tight list item, is wrapped with + *

...

. */ + ctx->containers[ctx->n_containers].is_loose = true; + ctx->n_containers++; + } + } + } else { + MD_CHECK(md_process_leaf_block(ctx, block)); + + if(block->type == MD_BLOCK_CODE || block->type == MD_BLOCK_HTML) + byte_off += block->n_lines * sizeof(MD_VERBATIMLINE); + else + byte_off += block->n_lines * sizeof(MD_LINE); + } + + byte_off += sizeof(MD_BLOCK); + } + + ctx->n_block_bytes = 0; + +abort: + return ret; +} + + +/************************************ + *** Grouping Lines into Blocks *** + ************************************/ + +static void* +md_push_block_bytes(MD_CTX* ctx, int n_bytes) +{ + void* ptr; + + if(ctx->n_block_bytes + n_bytes > ctx->alloc_block_bytes) { + void* new_block_bytes; + + ctx->alloc_block_bytes = (ctx->alloc_block_bytes > 0 + ? ctx->alloc_block_bytes + ctx->alloc_block_bytes / 2 + : 512); + new_block_bytes = realloc(ctx->block_bytes, ctx->alloc_block_bytes); + if(new_block_bytes == NULL) { + MD_LOG("realloc() failed."); + return NULL; + } + + /* Fix the ->current_block after the reallocation. */ + if(ctx->current_block != NULL) { + OFF off_current_block = (OFF) ((char*) ctx->current_block - (char*) ctx->block_bytes); + ctx->current_block = (MD_BLOCK*) ((char*) new_block_bytes + off_current_block); + } + + ctx->block_bytes = new_block_bytes; + } + + ptr = (char*)ctx->block_bytes + ctx->n_block_bytes; + ctx->n_block_bytes += n_bytes; + return ptr; +} + +static int +md_start_new_block(MD_CTX* ctx, const MD_LINE_ANALYSIS* line) +{ + MD_BLOCK* block; + + MD_ASSERT(ctx->current_block == NULL); + + block = (MD_BLOCK*) md_push_block_bytes(ctx, sizeof(MD_BLOCK)); + if(block == NULL) + return -1; + + switch(line->type) { + case MD_LINE_HR: + block->type = MD_BLOCK_HR; + break; + + case MD_LINE_ATXHEADER: + case MD_LINE_SETEXTHEADER: + block->type = MD_BLOCK_H; + break; + + case MD_LINE_FENCEDCODE: + case MD_LINE_INDENTEDCODE: + block->type = MD_BLOCK_CODE; + break; + + case MD_LINE_TEXT: + block->type = MD_BLOCK_P; + break; + + case MD_LINE_HTML: + block->type = MD_BLOCK_HTML; + break; + + case MD_LINE_BLANK: + case MD_LINE_SETEXTUNDERLINE: + case MD_LINE_TABLEUNDERLINE: + default: + MD_UNREACHABLE(); + break; + } + + block->flags = 0; + block->data = line->data; + block->n_lines = 0; + + ctx->current_block = block; + return 0; +} + +/* Forward declarations */ +static int md_is_hr_line(MD_CTX* ctx, OFF beg, OFF* p_end, OFF* p_killer); +static void* md_push_block_bytes(MD_CTX* ctx, int n_bytes); + +/* Eat from start of current (textual) block any reference definitions and/or + * footnote definitions, and remember them. + * + * (Such definitions can only be at start of it as they cannot break a + * paragraph.) + */ +static int +md_consume_link_reference_definitions(MD_CTX* ctx) +{ + MD_LINE* lines = (MD_LINE*) (ctx->current_block + 1); + MD_SIZE n_lines = ctx->current_block->n_lines; + MD_SIZE n = 0; + bool inject_hr = false; + OFF ignored; + + while(n < n_lines) { + int n_consumed = 0; + + /* When footnotes are enabled, try footnote definition first for lines + * starting with [^, so they are not accidentally consumed as link ref + * definitions (which would also match [^label]: url). */ + if((ctx->parser.flags & MD_FLAG_FOOTNOTES) && + lines[n].beg + 1 < ctx->size && + CH(lines[n].beg) == _T('[') && CH(lines[n].beg + 1) == _T('^')) + { + n_consumed = md_is_footnote_definition(ctx, lines + n, n_lines - n); + if(n_consumed < 0) + return -1; + } + + if(n_consumed == 0) { + n_consumed = md_is_link_reference_definition(ctx, lines + n, n_lines - n); + if(n_consumed < 0) + return -1; + } + + if(n_consumed == 0) + break; + + n += n_consumed; + } + + /* If no link ref. def. was detected, leave the block intact. */ + if(n == 0) + return 0; + + /* We may need to turn the first line after the link ref. def(s) into HR. + * (https://github.com/mity/md4c/issues/414) */ + if(n < n_lines && md_is_hr_line(ctx, lines[n].beg, &ignored, &ignored)) { + inject_hr = true; + n++; /* Remove one more line below. */ + } + + if(n == n_lines) { + /* Undo the whole block. */ + ctx->n_block_bytes -= n_lines * sizeof(MD_LINE); + ctx->n_block_bytes -= sizeof(MD_BLOCK); + ctx->current_block = NULL; + } else { + /* Remove some initial lines from the block. */ + memmove(lines, lines + n, (n_lines - n) * sizeof(MD_LINE)); + ctx->current_block->n_lines -= n; + ctx->n_block_bytes -= n * sizeof(MD_LINE); + } + + if(inject_hr) { + MD_BLOCK* hr_block; + + hr_block = md_push_block_bytes(ctx, sizeof(MD_BLOCK)); + if(hr_block == NULL) + return -1; + + if(ctx->current_block != NULL) { + memmove(ctx->current_block + 1, ctx->current_block, + (sizeof(MD_BLOCK) + ctx->current_block->n_lines * sizeof(MD_LINE))); + hr_block = ctx->current_block; + ctx->current_block++; + } + + memset(hr_block, 0, sizeof(MD_BLOCK)); + hr_block->type = MD_BLOCK_HR; + } + + return 0; +} + +static int +md_end_current_block(MD_CTX* ctx) +{ + int ret = 0; + + if(ctx->current_block == NULL) + return ret; + + /* Check whether there is a reference definition. (We do this here instead + * of in md_analyze_line() because reference definition can take multiple + * lines.) */ + if(ctx->current_block->type == MD_BLOCK_P || + (ctx->current_block->type == MD_BLOCK_H && (ctx->current_block->flags & MD_BLOCK_SETEXT_HEADER))) + { + MD_LINE* lines = (MD_LINE*) (ctx->current_block + 1); + if(lines[0].beg < ctx->size && CH(lines[0].beg) == _T('[')) { + MD_CHECK(md_consume_link_reference_definitions(ctx)); + if(ctx->current_block == NULL) + return ret; + } + } + + if(ctx->current_block->type == MD_BLOCK_H && (ctx->current_block->flags & MD_BLOCK_SETEXT_HEADER)) { + MD_SIZE n_lines = ctx->current_block->n_lines; + + if(n_lines > 1) { + /* Get rid of the underline. */ + ctx->current_block->n_lines--; + ctx->n_block_bytes -= sizeof(MD_LINE); + } else { + /* Only the underline has left after eating the ref. defs. + * Keep the line as beginning of a new ordinary paragraph. */ + ctx->current_block->type = MD_BLOCK_P; + return 0; + } + } + + /* Mark we are not building any block anymore. */ + ctx->current_block = NULL; + +abort: + return ret; +} + +static int +md_add_line_into_current_block(MD_CTX* ctx, const MD_LINE_ANALYSIS* analysis) +{ + MD_ASSERT(ctx->current_block != NULL); + + if(ctx->current_block->type == MD_BLOCK_CODE || ctx->current_block->type == MD_BLOCK_HTML) { + MD_VERBATIMLINE* line; + + line = (MD_VERBATIMLINE*) md_push_block_bytes(ctx, sizeof(MD_VERBATIMLINE)); + if(line == NULL) + return -1; + + line->indent = analysis->indent; + line->beg = analysis->beg; + line->end = analysis->end; + } else { + MD_LINE* line; + + line = (MD_LINE*) md_push_block_bytes(ctx, sizeof(MD_LINE)); + if(line == NULL) + return -1; + + line->beg = analysis->beg; + line->end = analysis->end; + } + ctx->current_block->n_lines++; + + return 0; +} + +/* Part of the MD_FLAG_PRESERVEBLANKLINES implementation. */ +static int +md_flush_blank_lines(MD_CTX* ctx) +{ + MD_BLOCK* block; + + if(ctx->n_blank_lines == 0) + return 0; + + block = (MD_BLOCK*) md_push_block_bytes(ctx, sizeof(MD_BLOCK)); + if(block == NULL) + return -1; + + block->type = MD_BLOCK_BLANK; + block->flags = 0; + block->data = ctx->n_blank_lines; + block->n_lines = 0; + + ctx->n_blank_lines = 0; + return 0; +} + +static int +md_push_container_bytes(MD_CTX* ctx, MD_BLOCKTYPE type, unsigned start, + unsigned data, unsigned flags) +{ + MD_BLOCK* block; + int ret = 0; + + MD_CHECK(md_flush_blank_lines(ctx)); + MD_CHECK(md_end_current_block(ctx)); + + block = (MD_BLOCK*) md_push_block_bytes(ctx, sizeof(MD_BLOCK)); + if(block == NULL) + return -1; + + block->type = type; + block->flags = flags; + block->data = data; + block->n_lines = start; + +abort: + return ret; +} + + + +/*********************** + *** Line Analysis *** + ***********************/ + +static int +md_is_hr_line(MD_CTX* ctx, OFF beg, OFF* p_end, OFF* p_killer) +{ + OFF off = beg + 1; + int n = 1; + + if(!ISANYOF(beg, _T("-_*"))) + return false; + + while(off < ctx->size && (CH(off) == CH(beg) || CH(off) == _T(' ') || CH(off) == _T('\t'))) { + if(CH(off) == CH(beg)) + n++; + off++; + } + + if(n < 3) { + *p_killer = off; + return false; + } + + /* Nothing else can be present on the line. */ + if(off < ctx->size && !ISNEWLINE(off)) { + *p_killer = off; + return false; + } + + *p_end = off; + return true; +} + +static int +md_is_atxheader_line(MD_CTX* ctx, OFF beg, OFF* p_beg, OFF* p_end, unsigned* p_level) +{ + int n; + OFF off = beg + 1; + + while(off < ctx->size && CH(off) == _T('#') && off - beg < 7) + off++; + n = off - beg; + + if(n > 6) + return false; + *p_level = n; + + if(!(ctx->parser.flags & MD_FLAG_PERMISSIVEATXHEADERS) && off < ctx->size && + !ISBLANK(off) && !ISNEWLINE(off)) + return false; + + while(off < ctx->size && ISBLANK(off)) + off++; + *p_beg = off; + *p_end = off; + return true; +} + +static int +md_is_setext_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_level) +{ + OFF off = beg + 1; + + while(off < ctx->size && CH(off) == CH(beg)) + off++; + + /* Optionally, space(s) or tabs can follow. */ + while(off < ctx->size && ISBLANK(off)) + off++; + + /* But nothing more is allowed on the line. */ + if(off < ctx->size && !ISNEWLINE(off)) + return false; + + *p_level = (CH(beg) == _T('=') ? 1 : 2); + *p_end = off; + return true; +} + +static int +md_is_table_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_col_count) +{ + OFF off = beg; + int found_pipe = false; + unsigned col_count = 0; + + if(off < ctx->size && CH(off) == _T('|')) { + found_pipe = true; + off++; + while(off < ctx->size && ISWHITESPACE(off)) + off++; + } + + while(1) { + int delimited = false; + + /* Cell underline ("-----", ":----", "----:" or ":----:") */ + if(off < ctx->size && CH(off) == _T(':')) + off++; + if(off >= ctx->size || CH(off) != _T('-')) + return false; + while(off < ctx->size && CH(off) == _T('-')) + off++; + if(off < ctx->size && CH(off) == _T(':')) + off++; + + col_count++; + + /* Pipe delimiter (optional at the end of line). */ + while(off < ctx->size && ISWHITESPACE(off)) + off++; + if(off < ctx->size && CH(off) == _T('|')) { + delimited = true; + found_pipe = true; + off++; + while(off < ctx->size && ISWHITESPACE(off)) + off++; + } + + /* Success, if we reach end of line. */ + if(off >= ctx->size || ISNEWLINE(off)) + break; + + if(!delimited) + return false; + } + + if(!found_pipe) + return false; + + *p_end = off; + *p_col_count = col_count; + return true; +} + +static int +md_is_opening_code_fence(MD_CTX* ctx, OFF beg, OFF* p_end) +{ + OFF off = beg; + + while(off < ctx->size && CH(off) == CH(beg)) + off++; + + /* Fence must have at least three characters. */ + if(off - beg < 3) + return false; + + ctx->code_fence_length = off - beg; + + /* Optionally, space(s) can follow. */ + while(off < ctx->size && CH(off) == _T(' ')) + off++; + + /* Optionally, an info string can follow. */ + while(off < ctx->size && !ISNEWLINE(off)) { + /* Backtick-based fence must not contain '`' in the info string. */ + if(CH(beg) == _T('`') && CH(off) == _T('`')) + return false; + off++; + } + + *p_end = off; + return true; +} + +static int +md_is_closing_code_fence(MD_CTX* ctx, CHAR ch, OFF beg, OFF* p_end) +{ + OFF off = beg; + int ret = false; + + /* Closing fence must have at least the same length and use same char as + * opening one. */ + while(off < ctx->size && CH(off) == ch) + off++; + if(off - beg < ctx->code_fence_length) + goto out; + + /* Optionally, space(s) can follow */ + while(off < ctx->size && ISANYOF2(off, _T(' '), _T('\t'))) + off++; + + /* But nothing more is allowed on the line. */ + if(off < ctx->size && !ISNEWLINE(off)) + goto out; + + ret = true; + +out: + /* Note we set *p_end even on failure: If we are not closing fence, caller + * would eat the line anyway without any parsing. */ + *p_end = off; + return ret; +} + + +/* Helper data for md_is_html_block_start_condition() and + * md_is_html_block_end_condition() */ +typedef struct TAG_tag TAG; +struct TAG_tag { + const CHAR* name; + unsigned len : 8; +}; + +#ifdef X + #undef X +#endif +#define X(name) { _T(name), (sizeof(_T(name))-1) / sizeof(CHAR) } +#define Xend { NULL, 0 } + +static const TAG t1[] = { X("pre"), X("script"), X("style"), X("textarea"), Xend }; + +static const TAG a6[] = { X("address"), X("article"), X("aside"), Xend }; +static const TAG b6[] = { X("base"), X("basefont"), X("blockquote"), X("body"), Xend }; +static const TAG c6[] = { X("caption"), X("center"), X("col"), X("colgroup"), Xend }; +static const TAG d6[] = { X("dd"), X("details"), X("dialog"), X("dir"), + X("div"), X("dl"), X("dt"), Xend }; +static const TAG f6[] = { X("fieldset"), X("figcaption"), X("figure"), X("footer"), + X("form"), X("frame"), X("frameset"), Xend }; +static const TAG h6[] = { X("h1"), X("h2"), X("h3"), X("h4"), X("h5"), X("h6"), + X("head"), X("header"), X("hr"), X("html"), Xend }; +static const TAG i6[] = { X("iframe"), Xend }; +static const TAG l6[] = { X("legend"), X("li"), X("link"), Xend }; +static const TAG m6[] = { X("main"), X("menu"), X("menuitem"), Xend }; +static const TAG n6[] = { X("nav"), X("noframes"), Xend }; +static const TAG o6[] = { X("ol"), X("optgroup"), X("option"), Xend }; +static const TAG p6[] = { X("p"), X("param"), Xend }; +static const TAG s6[] = { X("search"), X("section"), X("summary"), Xend }; +static const TAG t6[] = { X("table"), X("tbody"), X("td"), X("tfoot"), X("th"), + X("thead"), X("title"), X("tr"), X("track"), Xend }; +static const TAG u6[] = { X("ul"), Xend }; +static const TAG v6[] = { X("video"), Xend }; +static const TAG xx[] = { Xend }; + +#undef X +#undef Xend + +/* Returns type of the raw HTML block, or false if it is not HTML block. + * (Refer to CommonMark specification for details about the types.) + */ +static int +md_is_html_block_start_condition(MD_CTX* ctx, OFF beg) +{ + /* Type 6 is started by a long list of allowed tags. We use two-level + * tree to speed-up the search. */ + static const TAG* map6[26] = { + a6, b6, c6, d6, xx, f6, xx, h6, i6, xx, xx, l6, m6, + n6, o6, p6, xx, xx, s6, t6, u6, v6, xx, xx, xx, xx + }; + OFF off = beg + 1; + int i; + + /* Check for type 1: size) { + if(md_ascii_case_eq(STR(off), t1[i].name, t1[i].len)) + return 1; + } + } + + /* Check for type 2: "), 3, p_end) ? 2 : false); + + case 3: + return (md_line_contains(ctx, beg, _T("?>"), 2, p_end) ? 3 : false); + + case 4: + return (md_line_contains(ctx, beg, _T(">"), 1, p_end) ? 4 : false); + + case 5: + return (md_line_contains(ctx, beg, _T("]]>"), 3, p_end) ? 5 : false); + + case 6: MD_FALLTHROUGH(); + case 7: + if(beg >= ctx->size || ISNEWLINE(beg)) { + /* Blank line ends types 6 and 7. */ + *p_end = beg; + return ctx->html_block_type; + } + return false; + + default: + MD_UNREACHABLE(); + } + return false; +} + + +static int +md_is_container_compatible(const MD_CONTAINER* pivot, const MD_CONTAINER* container) +{ + /* Block quote has no "items" like lists. */ + if(container->ch == _T('>')) + return false; + + if(container->ch != pivot->ch) + return false; + if(container->mark_indent > pivot->contents_indent) + return false; + + return true; +} + +static int +md_push_container(MD_CTX* ctx, const MD_CONTAINER* container) +{ + if(ctx->n_containers >= ctx->alloc_containers) { + MD_CONTAINER* new_containers; + + ctx->alloc_containers = (ctx->alloc_containers > 0 + ? ctx->alloc_containers + ctx->alloc_containers / 2 + : 16); + new_containers = realloc(ctx->containers, ctx->alloc_containers * sizeof(MD_CONTAINER)); + if(new_containers == NULL) { + MD_LOG("realloc() failed."); + return -1; + } + + ctx->containers = new_containers; + } + + memcpy(&ctx->containers[ctx->n_containers++], container, sizeof(MD_CONTAINER)); + return 0; +} + +static int +md_enter_child_containers(MD_CTX* ctx, int n_children) +{ + int i; + int ret = 0; + + for(i = ctx->n_containers - n_children; i < ctx->n_containers; i++) { + MD_CONTAINER* c = &ctx->containers[i]; + int is_ordered_list = false; + + switch(c->ch) { + case _T(')'): + case _T('.'): + is_ordered_list = true; + MD_FALLTHROUGH(); + + case _T('-'): + case _T('+'): + case _T('*'): + /* Remember offset in ctx->block_bytes so we can revisit the + * block if we detect it is a loose list. */ + MD_CHECK(md_end_current_block(ctx)); + c->block_byte_off = ctx->n_block_bytes; + + MD_CHECK(md_push_container_bytes(ctx, + (is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL), + c->start, c->ch, MD_BLOCK_CONTAINER_OPENER)); + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + c->task_mark_off, + (c->is_task ? CH(c->task_mark_off) : 0), + MD_BLOCK_CONTAINER_OPENER)); + break; + + case _T('>'): + MD_CHECK(md_push_container_bytes(ctx, + (c->is_admonition ? MD_BLOCK_ADMONITION : MD_BLOCK_QUOTE), + 0, c->admonition_type, MD_BLOCK_CONTAINER_OPENER)); + break; + + default: + MD_UNREACHABLE(); + break; + } + } + +abort: + return ret; +} + +static int +md_leave_child_containers(MD_CTX* ctx, int n_keep) +{ + int ret = 0; + + while(ctx->n_containers > n_keep) { + MD_CONTAINER* c = &ctx->containers[ctx->n_containers-1]; + int is_ordered_list = false; + + switch(c->ch) { + case _T(')'): + case _T('.'): + is_ordered_list = true; + MD_FALLTHROUGH(); + + case _T('-'): + case _T('+'): + case _T('*'): + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + c->task_mark_off, (c->is_task ? CH(c->task_mark_off) : 0), + MD_BLOCK_CONTAINER_CLOSER)); + MD_CHECK(md_push_container_bytes(ctx, + (is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL), 0, + c->ch, MD_BLOCK_CONTAINER_CLOSER)); + break; + + case _T('>'): + MD_CHECK(md_push_container_bytes(ctx, + (c->is_admonition ? MD_BLOCK_ADMONITION : MD_BLOCK_QUOTE), + 0, c->admonition_type, MD_BLOCK_CONTAINER_CLOSER)); + break; + + default: + MD_UNREACHABLE(); + break; + } + + ctx->n_containers--; + } + +abort: + return ret; +} + +static int +md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTAINER* p_container) +{ + OFF off = beg; + OFF max_end; + + if(off >= ctx->size || indent >= ctx->code_indent_offset) + return false; + + /* Check for block quote mark. */ + if(CH(off) == _T('>')) { + off++; + p_container->ch = _T('>'); + p_container->is_loose = false; + p_container->is_task = false; + p_container->mark_indent = indent; + p_container->contents_indent = indent + 1; + *p_end = off; + return true; + } + + /* Check for list item bullet mark. */ + if(ISANYOF(off, _T("-+*")) && (off+1 >= ctx->size || ISBLANK(off+1) || ISNEWLINE(off+1))) { + p_container->ch = CH(off); + p_container->is_loose = false; + p_container->is_task = false; + p_container->mark_indent = indent; + p_container->contents_indent = indent + 1; + *p_end = off+1; + return true; + } + + /* Check for ordered list item marks. */ + max_end = off + 9; + if(max_end > ctx->size) + max_end = ctx->size; + p_container->start = 0; + while(off < max_end && ISDIGIT(off)) { + p_container->start = p_container->start * 10 + CH(off) - _T('0'); + off++; + } + if(off > beg && + off < ctx->size && + (CH(off) == _T('.') || CH(off) == _T(')')) && + (off+1 >= ctx->size || ISBLANK(off+1) || ISNEWLINE(off+1))) + { + p_container->ch = CH(off); + p_container->is_loose = false; + p_container->is_task = false; + p_container->mark_indent = indent; + p_container->contents_indent = indent + off - beg + 1; + *p_end = off+1; + return true; + } + + return false; +} + +static unsigned +md_line_indentation(MD_CTX* ctx, unsigned total_indent, OFF beg, OFF* p_end) +{ + OFF off = beg; + unsigned indent = total_indent; + + while(off < ctx->size && ISBLANK(off)) { + if(CH(off) == _T('\t')) + indent = (indent + 4) & ~3; + else + indent++; + off++; + } + + *p_end = off; + return indent - total_indent; +} + +static const MD_LINE_ANALYSIS md_dummy_blank_line = { MD_LINE_BLANK, 0, 0, 0, 0, 0 }; + +/* Analyze type of the line and find some its properties. This serves as a + * main input for determining type and boundaries of a block. */ +static int +md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, + const MD_LINE_ANALYSIS* pivot_line, MD_LINE_ANALYSIS* line) +{ + unsigned total_indent = 0; + int n_parents = 0; + int n_brothers = 0; + int n_children = 0; + MD_CONTAINER container = { 0 }; + int prev_line_has_list_loosening_effect = ctx->last_line_has_list_loosening_effect; + OFF off = beg; + OFF hr_killer = 0; + int ret = 0; + + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + line->beg = off; + line->enforce_new_block = false; + + /* Given the indentation and block quote marks '>', determine how many of + * the current containers are our parents. */ + while(n_parents < ctx->n_containers) { + MD_CONTAINER* c = &ctx->containers[n_parents]; + + if(c->ch == _T('>') && line->indent < ctx->code_indent_offset && + off < ctx->size && CH(off) == _T('>')) + { + /* Block quote mark. */ + off++; + total_indent++; + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + + /* The optional 1st space after '>' is part of the block quote mark. */ + if(line->indent > 0) + line->indent--; + + line->beg = off; + + } else if(c->ch != _T('>') && line->indent >= c->contents_indent) { + /* List. */ + line->indent -= c->contents_indent; + } else { + break; + } + + n_parents++; + } + + if(off >= ctx->size || ISNEWLINE(off)) { + /* Blank line does not need any real indentation to be nested inside + * a list. */ + if(n_brothers + n_children == 0) { + while(n_parents < ctx->n_containers && ctx->containers[n_parents].ch != _T('>')) + n_parents++; + } + } + + while(true) { + /* Check whether we are fenced code continuation. */ + if(pivot_line->type == MD_LINE_FENCEDCODE) { + line->beg = off; + + /* We are another MD_LINE_FENCEDCODE unless we are closing fence + * which we transform into MD_LINE_BLANK. */ + if(line->indent < ctx->code_indent_offset) { + if(md_is_closing_code_fence(ctx, CH(pivot_line->beg), off, &off)) { + line->type = MD_LINE_BLANK; + ctx->last_line_has_list_loosening_effect = false; + break; + } + } + + /* Change indentation accordingly to the initial code fence. */ + if(n_parents == ctx->n_containers) { + if(line->indent > pivot_line->indent) + line->indent -= pivot_line->indent; + else + line->indent = 0; + + line->type = MD_LINE_FENCEDCODE; + break; + } + } + + /* Check whether we are HTML block continuation. */ + if(pivot_line->type == MD_LINE_HTML && ctx->html_block_type > 0) { + if(n_parents < ctx->n_containers) { + /* HTML block is implicitly ended if the enclosing container + * block ends. */ + ctx->html_block_type = 0; + } else { + int html_block_type; + + html_block_type = md_is_html_block_end_condition(ctx, off, &off); + if(html_block_type > 0) { + MD_ASSERT(html_block_type == ctx->html_block_type); + + /* Make sure this is the last line of the block. */ + ctx->html_block_type = 0; + + /* Some end conditions serve as blank lines at the same time. */ + if(html_block_type == 6 || html_block_type == 7) { + line->type = MD_LINE_BLANK; + line->indent = 0; + break; + } + } + + line->type = MD_LINE_HTML; + n_parents = ctx->n_containers; + break; + } + } + + /* Check for blank line. */ + if(off >= ctx->size || ISNEWLINE(off)) { + if(pivot_line->type == MD_LINE_INDENTEDCODE && n_parents == ctx->n_containers) { + line->type = MD_LINE_INDENTEDCODE; + if(line->indent > ctx->code_indent_offset) + line->indent -= ctx->code_indent_offset; + else + line->indent = 0; + ctx->last_line_has_list_loosening_effect = false; + } else { + line->type = MD_LINE_BLANK; + ctx->consecutive_blank_lines++; + ctx->last_line_has_list_loosening_effect = (n_parents > 0 && + n_brothers + n_children == 0 && + ctx->containers[n_parents-1].ch != _T('>')); + } + break; + } else { + /* CommonMark requires a list item cannot begin with two (or more) + * blank lines so we may need to forcefully end the list. + * (See https://github.com/mity/md4c/issues/6) */ + if(ctx->consecutive_blank_lines >= 2) { + if(n_parents > 0 && n_parents == ctx->n_containers && + ctx->containers[n_parents-1].ch != _T('>') && + n_brothers + n_children == 0 && ctx->current_block == NULL && + ctx->n_block_bytes > (int) sizeof(MD_BLOCK)) + { + MD_BLOCK* top_block = (MD_BLOCK*) ((char*)ctx->block_bytes + ctx->n_block_bytes - sizeof(MD_BLOCK)); + if(top_block->type == MD_BLOCK_LI) { + n_parents--; + + line->indent = total_indent; + if(n_parents > 0) + line->indent -= MIN(line->indent, ctx->containers[n_parents-1].contents_indent); + } + } + } + ctx->consecutive_blank_lines = 0; + + ctx->last_line_has_list_loosening_effect = false; + } + + /* Check whether we are Setext underline. */ + if(line->indent < ctx->code_indent_offset && pivot_line->type == MD_LINE_TEXT + && off < ctx->size && ISANYOF2(off, _T('='), _T('-')) + && (n_parents == ctx->n_containers)) + { + unsigned level; + + if(md_is_setext_underline(ctx, off, &off, &level)) { + line->type = MD_LINE_SETEXTUNDERLINE; + line->data = level; + break; + } + } + + /* Check for thematic break line. */ + if(line->indent < ctx->code_indent_offset + && off < ctx->size && off >= hr_killer) + { + if(md_is_hr_line(ctx, off, &off, &hr_killer)) { + line->type = MD_LINE_HR; + break; + } + } + + /* Check for "brother" container. I.e. whether we are another list item + * in already started list. */ + if(n_parents < ctx->n_containers && n_brothers + n_children == 0) { + OFF tmp; + + if(md_is_container_mark(ctx, line->indent, off, &tmp, &container) && + md_is_container_compatible(&ctx->containers[n_parents], &container)) + { + pivot_line = &md_dummy_blank_line; + + off = tmp; + + total_indent += container.contents_indent - container.mark_indent; + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + line->beg = off; + + /* Some of the following whitespace actually still belongs to the mark. */ + if(off >= ctx->size || ISNEWLINE(off)) { + container.contents_indent++; + } else if(line->indent <= ctx->code_indent_offset) { + container.contents_indent += line->indent; + line->indent = 0; + } else { + container.contents_indent += 1; + line->indent--; + } + + ctx->containers[n_parents].mark_indent = container.mark_indent; + ctx->containers[n_parents].contents_indent = container.contents_indent; + + n_brothers++; + continue; + } + } + + /* Check for indented code. + * Note indented code block cannot interrupt a paragraph. */ + if(line->indent >= ctx->code_indent_offset && (pivot_line->type != MD_LINE_TEXT)) { + line->type = MD_LINE_INDENTEDCODE; + line->indent -= ctx->code_indent_offset; + line->data = 0; + break; + } + + /* Check for start of a new container block. */ + if(line->indent < ctx->code_indent_offset && + md_is_container_mark(ctx, line->indent, off, &off, &container)) + { + if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers && + (off >= ctx->size || ISNEWLINE(off)) && container.ch != _T('>')) + { + /* Noop. List mark followed by a blank line cannot interrupt a paragraph. */ + } else if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers && + ISANYOF2_(container.ch, _T('.'), _T(')')) && container.start != 1) + { + /* Noop. Ordered list cannot interrupt a paragraph unless the start index is 1. */ + } else { + total_indent += container.contents_indent - container.mark_indent; + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + + line->beg = off; + line->data = container.ch; + + /* Some of the following whitespace actually still belongs to the mark. */ + if(off >= ctx->size || ISNEWLINE(off)) { + container.contents_indent++; + } else if(line->indent <= ctx->code_indent_offset) { + container.contents_indent += line->indent; + line->indent = 0; + } else { + container.contents_indent += 1; + line->indent--; + } + + if(n_brothers + n_children == 0) + pivot_line = &md_dummy_blank_line; + + if(n_children == 0) + MD_CHECK(md_leave_child_containers(ctx, n_parents + n_brothers)); + + n_children++; + MD_CHECK(md_push_container(ctx, &container)); + continue; + } + } + + /* Check whether we are table continuation. */ + if(pivot_line->type == MD_LINE_TABLE && n_parents == ctx->n_containers) { + line->type = MD_LINE_TABLE; + break; + } + + /* Check for ATX header. */ + if(line->indent < ctx->code_indent_offset && + off < ctx->size && CH(off) == _T('#')) + { + unsigned level; + + if(md_is_atxheader_line(ctx, off, &line->beg, &off, &level)) { + line->type = MD_LINE_ATXHEADER; + line->data = level; + break; + } + } + + /* Check whether we are starting code fence. */ + if(line->indent < ctx->code_indent_offset && + off < ctx->size && ISANYOF2(off, _T('`'), _T('~'))) + { + if(md_is_opening_code_fence(ctx, off, &off)) { + line->type = MD_LINE_FENCEDCODE; + line->data = 1; + line->enforce_new_block = true; + break; + } + } + + /* Check for start of raw HTML block. */ + if(off < ctx->size && CH(off) == _T('<') + && !(ctx->parser.flags & MD_FLAG_NOHTMLBLOCKS)) + { + ctx->html_block_type = md_is_html_block_start_condition(ctx, off); + + /* HTML block type 7 cannot interrupt paragraph. */ + if(ctx->html_block_type == 7 && pivot_line->type == MD_LINE_TEXT) + ctx->html_block_type = 0; + + if(ctx->html_block_type > 0) { + /* The line itself also may immediately close the block. */ + if(md_is_html_block_end_condition(ctx, off, &off) == ctx->html_block_type) { + /* Make sure this is the last line of the block. */ + ctx->html_block_type = 0; + } + + line->enforce_new_block = true; + line->type = MD_LINE_HTML; + break; + } + } + + /* Check for table underline. */ + if((ctx->parser.flags & MD_FLAG_TABLES) && pivot_line->type == MD_LINE_TEXT + && off < ctx->size && ISANYOF3(off, _T('|'), _T('-'), _T(':')) + && n_parents == ctx->n_containers) + { + unsigned col_count; + + if(ctx->current_block != NULL && ctx->current_block->n_lines == 1 && + md_is_table_underline(ctx, off, &off, &col_count)) + { + line->data = col_count; + line->type = MD_LINE_TABLEUNDERLINE; + break; + } + } + + /* By default, we are normal text line. */ + line->type = MD_LINE_TEXT; + if(pivot_line->type == MD_LINE_TEXT && n_brothers + n_children == 0) { + /* Lazy continuation. */ + n_parents = ctx->n_containers; + } + + /* Check for task mark. */ + if((ctx->parser.flags & MD_FLAG_TASKLISTS) && n_brothers + n_children > 0 && + ISANYOF_(ctx->containers[ctx->n_containers-1].ch, _T("-+*.)"))) + { + OFF tmp = off; + + while(tmp < ctx->size && tmp < off + 3 && ISBLANK(tmp)) + tmp++; + if(tmp + 2 < ctx->size && CH(tmp) == _T('[') && + ISANYOF(tmp+1, _T("xX ")) && CH(tmp+2) == _T(']') && + (tmp + 3 == ctx->size || ISBLANK(tmp+3) || ISNEWLINE(tmp+3))) + { + MD_CONTAINER* task_container = (n_children > 0 ? &ctx->containers[ctx->n_containers-1] : &container); + task_container->is_task = true; + task_container->task_mark_off = tmp + 1; + off = tmp + 3; + while(off < ctx->size && ISWHITESPACE(off)) + off++; + line->beg = off; + } + } + + break; + } + + /* Scan for end of the line. */ + /* Optimization: Use some loop unrolling. */ + while(off + 3 < ctx->size && !ISNEWLINE(off+0) && !ISNEWLINE(off+1) + && !ISNEWLINE(off+2) && !ISNEWLINE(off+3)) + off += 4; + while(off < ctx->size && !ISNEWLINE(off)) + off++; + + /* Set end of the line. */ + line->end = off; + + /* But for ATX header, we should exclude the optional trailing mark. */ + if(line->type == MD_LINE_ATXHEADER) { + OFF tmp = line->end; + while(tmp > line->beg && ISBLANK(tmp-1)) + tmp--; + while(tmp > line->beg && CH(tmp-1) == _T('#')) + tmp--; + if(tmp == line->beg || ISBLANK(tmp-1) || (ctx->parser.flags & MD_FLAG_PERMISSIVEATXHEADERS)) + line->end = tmp; + } + + /* Trim trailing spaces. */ + if(line->type != MD_LINE_INDENTEDCODE && line->type != MD_LINE_FENCEDCODE && line->type != MD_LINE_HTML) { + while(line->end > line->beg && ISBLANK(line->end-1)) + line->end--; + } + + /* Eat also the new line. */ + if(off < ctx->size && CH(off) == _T('\r')) + off++; + if(off < ctx->size && CH(off) == _T('\n')) + off++; + + *p_end = off; + + /* If we belong to a list after seeing a blank line, the list is loose. */ + if(prev_line_has_list_loosening_effect && line->type != MD_LINE_BLANK && n_parents + n_brothers > 0) { + MD_CONTAINER* c = &ctx->containers[n_parents + n_brothers - 1]; + if(c->ch != _T('>')) { + MD_BLOCK* block = (MD_BLOCK*) (((char*)ctx->block_bytes) + c->block_byte_off); + block->flags |= MD_BLOCK_LOOSE_LIST; + } + } + + /* Leave any containers we are not part of anymore. */ + if(n_children == 0 && n_parents + n_brothers < ctx->n_containers) + MD_CHECK(md_leave_child_containers(ctx, n_parents + n_brothers)); + + /* Enter any container we found a mark for. */ + if(n_brothers > 0) { + MD_ASSERT(n_brothers == 1); + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + ctx->containers[n_parents].task_mark_off, + (ctx->containers[n_parents].is_task ? CH(ctx->containers[n_parents].task_mark_off) : 0), + MD_BLOCK_CONTAINER_CLOSER)); + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + container.task_mark_off, + (container.is_task ? CH(container.task_mark_off) : 0), + MD_BLOCK_CONTAINER_OPENER)); + ctx->containers[n_parents].is_task = container.is_task; + ctx->containers[n_parents].task_mark_off = container.task_mark_off; + } + + if(n_children > 0) { + /* Check for admonition tag. */ + if((ctx->parser.flags & MD_FLAG_ADMONITIONS) && n_children > 0 && + ctx->containers[ctx->n_containers-1].ch == _T('>') && line->type == MD_LINE_TEXT && + 3 < line->end - line->beg && line->end - line->beg < 16 && + CH(line->beg) == _T('[') && CH(line->beg+1) == _T('!') && CH(line->end-1) == _T(']')) + { + unsigned i; + + for(i = 0; i < SIZEOF_ARRAY(MD_ADMONITION_TAGS); i++) { + if(line->end - line->beg == md_strlen(MD_ADMONITION_TAGS[i]) + 3 && + md_ascii_case_eq(STR(line->beg+2), MD_ADMONITION_TAGS[i], line->end - line->beg - 3)) + { + ctx->containers[ctx->n_containers-1].is_admonition = true; + ctx->containers[ctx->n_containers-1].admonition_type = i; + line->type = MD_LINE_BLANK; + break; + } + } + } + + /* Enter all the child container blocks. */ + MD_CHECK(md_enter_child_containers(ctx, n_children)); + } + +abort: + return ret; +} + +static int +md_process_line(MD_CTX* ctx, const MD_LINE_ANALYSIS** p_pivot_line, MD_LINE_ANALYSIS* line) +{ + const MD_LINE_ANALYSIS* pivot_line = *p_pivot_line; + int ret = 0; + + /* Blank line ends current leaf block. */ + if(line->type == MD_LINE_BLANK) { + MD_CHECK(md_end_current_block(ctx)); + /* Count only genuinely empty lines: some non-blank lines (e.g. a closing + * code fence) are internally retyped as MD_LINE_BLANK but still hold + * their text (beg < end), and must not be counted. */ + if((ctx->parser.flags & MD_FLAG_PRESERVEBLANKLINES) && line->beg >= line->end) + ctx->n_blank_lines++; + *p_pivot_line = &md_dummy_blank_line; + return 0; + } + + /* The blank lines preceding this block (if any) form a block separation + * which we report before the block itself. */ + MD_CHECK(md_flush_blank_lines(ctx)); + + if(line->enforce_new_block) + MD_CHECK(md_end_current_block(ctx)); + + /* Some line types form block on their own. */ + if(line->type == MD_LINE_HR || line->type == MD_LINE_ATXHEADER) { + MD_CHECK(md_end_current_block(ctx)); + + /* Add our single-line block. */ + MD_CHECK(md_start_new_block(ctx, line)); + MD_CHECK(md_add_line_into_current_block(ctx, line)); + MD_CHECK(md_end_current_block(ctx)); + *p_pivot_line = &md_dummy_blank_line; + return 0; + } + + /* MD_LINE_SETEXTUNDERLINE changes meaning of the current block and ends it. */ + if(line->type == MD_LINE_SETEXTUNDERLINE) { + MD_ASSERT(ctx->current_block != NULL); + ctx->current_block->type = MD_BLOCK_H; + ctx->current_block->data = line->data; + ctx->current_block->flags |= MD_BLOCK_SETEXT_HEADER; + MD_CHECK(md_add_line_into_current_block(ctx, line)); + MD_CHECK(md_end_current_block(ctx)); + if(ctx->current_block == NULL) { + *p_pivot_line = &md_dummy_blank_line; + } else { + /* This happens if we have consumed all the body as link ref. defs. + * and downgraded the underline into start of a new paragraph block. */ + line->type = MD_LINE_TEXT; + *p_pivot_line = line; + } + return 0; + } + + /* MD_LINE_TABLEUNDERLINE changes meaning of the current block. */ + if(line->type == MD_LINE_TABLEUNDERLINE) { + MD_ASSERT(ctx->current_block != NULL); + MD_ASSERT(ctx->current_block->n_lines == 1); + ctx->current_block->type = MD_BLOCK_TABLE; + ctx->current_block->data = line->data; + MD_ASSERT(pivot_line != &md_dummy_blank_line); + ((MD_LINE_ANALYSIS*)pivot_line)->type = MD_LINE_TABLE; + MD_CHECK(md_add_line_into_current_block(ctx, line)); + return 0; + } + + /* The current block also ends if the line has different type. */ + if(line->type != pivot_line->type) + MD_CHECK(md_end_current_block(ctx)); + + /* The current line may start a new block. */ + if(ctx->current_block == NULL) { + MD_CHECK(md_start_new_block(ctx, line)); + *p_pivot_line = line; + } + + /* In all other cases the line is just a continuation of the current block. */ + MD_CHECK(md_add_line_into_current_block(ctx, line)); + +abort: + return ret; +} + +static int +md_footnote_def_cmp_index(const void* a, const void* b) +{ + const MD_FOOTNOTE_DEF* da = (const MD_FOOTNOTE_DEF*) a; + const MD_FOOTNOTE_DEF* db = (const MD_FOOTNOTE_DEF*) b; + + /* Unreferenced defs (index == 0) always sort after referenced ones. */ + if(da->index == 0 && db->index == 0) return 0; + if(da->index == 0) return +1; + if(db->index == 0) return -1; + if(da->index < db->index) return -1; + if(da->index > db->index) return +1; + return 0; +} + +static int +md_process_footnote_def(MD_CTX* ctx, MD_FOOTNOTE_DEF* def) +{ + MD_BLOCK_FOOTNOTE_DEF_DETAIL det; + MD_ATTRIBUTE_BUILD label_build = { 0 }; + int ret = 0; + + memset(&det, 0, sizeof(MD_BLOCK_FOOTNOTE_DEF_DETAIL)); + det.id = def->index; + det.ref_count = def->ref_count; + MD_CHECK(md_build_attribute(ctx, def->entry.label, def->entry.label_size, 0, + &det.label, &label_build)); + + MD_ENTER_BLOCK(MD_BLOCK_FOOTNOTE_DEF, &det); + MD_CHECK(md_process_normal_block_contents(ctx, def->content_lines, + def->n_content_lines)); + MD_LEAVE_BLOCK(MD_BLOCK_FOOTNOTE_DEF, &det); + +abort: + md_free_attribute(ctx, &label_build); + return ret; +} + +/* Render footnote definitions that were actually referenced, in reference order. + * Called from md_process_doc() after md_process_all_blocks(). */ +static int +md_process_footnote_defs(MD_CTX* ctx) +{ + unsigned i; + int ret = 0; + + if(ctx->footnote_hashtable.n_defs == 0 || ctx->next_footnote_index == 0) + return 0; + + /* Sort defs by index so we emit in reference order. */ + qsort(ctx->footnote_hashtable.defs, ctx->footnote_hashtable.n_defs, + sizeof(MD_FOOTNOTE_DEF), md_footnote_def_cmp_index); + + MD_ENTER_BLOCK(MD_BLOCK_FOOTNOTE_DEF_SECTION, NULL); + + for(i = 0; i < ctx->footnote_hashtable.n_defs; i++) { + MD_FOOTNOTE_DEF* def = &ctx->footnote_hashtable.footnote_defs[i]; + if(def->index == 0) + break; + MD_CHECK(md_process_footnote_def(ctx, def)); + } + + MD_LEAVE_BLOCK(MD_BLOCK_FOOTNOTE_DEF_SECTION, NULL); + +abort: + return ret; +} + +static int +md_process_doc(MD_CTX *ctx) +{ + const MD_LINE_ANALYSIS* pivot_line = &md_dummy_blank_line; + MD_LINE_ANALYSIS line_buf[2]; + MD_LINE_ANALYSIS* line = &line_buf[0]; + OFF off = 0; + int ret = 0; + + MD_ENTER_BLOCK(MD_BLOCK_DOC, NULL); + + while(off < ctx->size) { + if(line == pivot_line) + line = (line == &line_buf[0] ? &line_buf[1] : &line_buf[0]); + + MD_CHECK(md_analyze_line(ctx, off, &off, pivot_line, line)); + MD_CHECK(md_process_line(ctx, &pivot_line, line)); + } + + MD_CHECK(md_end_current_block(ctx)); + + MD_CHECK(md_build_ref_def_hashtable(ctx)); + if(ctx->parser.flags & MD_FLAG_FOOTNOTES) + MD_CHECK(md_build_footnote_def_hashtable(ctx)); + + /* Process all blocks. */ + MD_CHECK(md_leave_child_containers(ctx, 0)); + /* Report any blank lines trailing the document. */ + MD_CHECK(md_flush_blank_lines(ctx)); + MD_CHECK(md_process_all_blocks(ctx)); + + /* Emit footnote definitions that were referenced, in reference order. */ + if(ctx->parser.flags & MD_FLAG_FOOTNOTES) + MD_CHECK(md_process_footnote_defs(ctx)); + + MD_LEAVE_BLOCK(MD_BLOCK_DOC, NULL); + +abort: + +#if 0 + /* Output some memory consumption statistics. */ + { + char buffer[256]; + sprintf(buffer, "Alloced %u bytes for block buffer.", + (unsigned)(ctx->alloc_block_bytes)); + MD_LOG(buffer); + + sprintf(buffer, "Alloced %u bytes for containers buffer.", + (unsigned)(ctx->alloc_containers * sizeof(MD_CONTAINER))); + MD_LOG(buffer); + + sprintf(buffer, "Alloced %u bytes for marks buffer.", + (unsigned)(ctx->alloc_marks * sizeof(MD_MARK))); + MD_LOG(buffer); + + sprintf(buffer, "Alloced %u bytes for aux. buffer.", + (unsigned)(ctx->alloc_buffer * sizeof(MD_CHAR))); + MD_LOG(buffer); + } +#endif + + return ret; +} + + +/******************** + *** Public API *** + ********************/ + +int +md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata) +{ + MD_CTX ctx; + int i; + int ret; + + if(parser->abi_version != 0) { + if(parser->debug_log != NULL) + parser->debug_log("Unsupported abi_version.", userdata); + return -1; + } + + /* Setup context structure. */ + memset(&ctx, 0, sizeof(MD_CTX)); + ctx.text = text; + ctx.size = size; + memcpy(&ctx.parser, parser, sizeof(MD_PARSER)); + ctx.userdata = userdata; + ctx.code_indent_offset = (ctx.parser.flags & MD_FLAG_NOINDENTEDCODEBLOCKS) ? (OFF)(-1) : 4; + md_build_mark_char_map(&ctx); + ctx.doc_ends_with_newline = (size > 0 && ISNEWLINE_(text[size-1])); + ctx.ref_def_hashtable.def_size = sizeof(MD_REF_DEF); + ctx.max_ref_def_output = 16 * MIN(size, (MD_SIZE)(1024 * 1024 / 16)); + ctx.footnote_hashtable.def_size = sizeof(MD_FOOTNOTE_DEF); + + /* Reset all mark stacks and lists. */ + for(i = 0; i < (int) SIZEOF_ARRAY(ctx.opener_stacks); i++) + ctx.opener_stacks[i].top = -1; + ctx.ptr_stack.top = -1; + ctx.unresolved_link_head = -1; + ctx.unresolved_link_tail = -1; + ctx.table_cell_boundaries_head = -1; + ctx.table_cell_boundaries_tail = -1; + + /* All the work. */ + ret = md_process_doc(&ctx); + + /* Clean-up. */ + md_free_ref_defs(&ctx); + md_free_footnote_defs(&ctx); + free(ctx.buffer); + free(ctx.marks); + free(ctx.block_bytes); + free(ctx.containers); + + return ret; +} diff --git a/external/md4c.h b/external/md4c.h new file mode 100644 index 0000000..7a6896a --- /dev/null +++ b/external/md4c.h @@ -0,0 +1,495 @@ +/* + * MD4C: Markdown parser for C + * (https://github.com/mity/md4c) + * + * Copyright (c) 2016-2026 Martin Mitáš + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef MD4C_H +#define MD4C_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined MD4C_USE_UTF16 + /* Magic to support UTF-16. Note that in order to use it, you have to define + * the macro MD4C_USE_UTF16 both when building MD4C as well as when + * including this header in your code. */ + #ifdef _WIN32 + #include + typedef WCHAR MD_CHAR; + #else + #error MD4C_USE_UTF16 is only supported on Windows. + #endif +#else + typedef char MD_CHAR; +#endif + +typedef unsigned MD_SIZE; +typedef unsigned MD_OFFSET; + + +/* Block represents a part of document hierarchy structure like a paragraph + * or list item. + */ +typedef enum MD_BLOCKTYPE { + /* ... */ + MD_BLOCK_DOC = 0, + + /*
...
*/ + MD_BLOCK_QUOTE, + + /*
    ...
+ * Detail: Structure MD_BLOCK_UL_DETAIL. */ + MD_BLOCK_UL, + + /*
    ...
+ * Detail: Structure MD_BLOCK_OL_DETAIL. */ + MD_BLOCK_OL, + + /*
  • ...
  • + * Detail: Structure MD_BLOCK_LI_DETAIL. */ + MD_BLOCK_LI, + + /*
    */ + MD_BLOCK_HR, + + /*

    ...

    (for levels up to 6) + * Detail: Structure MD_BLOCK_H_DETAIL. */ + MD_BLOCK_H, + + /*
    ...
    + * Note the text lines within code blocks are terminated with '\n' + * instead of explicit MD_TEXT_BR. */ + MD_BLOCK_CODE, + + /* Raw HTML block. This itself does not correspond to any particular HTML + * tag. The contents of it _is_ raw HTML source intended to be put + * in verbatim form to the HTML output. */ + MD_BLOCK_HTML, + + /*

    ...

    */ + MD_BLOCK_P, + + /* ...
    and its contents. + * Detail: Structure MD_BLOCK_TABLE_DETAIL (for MD_BLOCK_TABLE), + * structure MD_BLOCK_TD_DETAIL (for MD_BLOCK_TH and MD_BLOCK_TD) + * Note all of these are used only if extension MD_FLAG_TABLES is enabled. */ + MD_BLOCK_TABLE, + MD_BLOCK_THEAD, + MD_BLOCK_TBODY, + MD_BLOCK_TR, + MD_BLOCK_TH, + MD_BLOCK_TD, + + /* Container for all referenced footnote definitions, rendered at the end + * of the document. + * Detail: NULL. + * Note: Used only if extension MD_FLAG_FOOTNOTES is enabled, and only when + * at least one footnote definition is referenced. */ + MD_BLOCK_FOOTNOTE_DEF_SECTION, + + /* A single footnote definition, rendered at the end of the document. + * Detail: Structure MD_BLOCK_FOOTNOTE_DEF_DETAIL. + * Note: Used only if extension MD_FLAG_FOOTNOTES is enabled. + * Only definitions that are actually referenced in the document are + * emitted, in order of first reference. */ + MD_BLOCK_FOOTNOTE_DEF, + + /* Adminition extension. + * Detail MD_BLOCK_ADMONITION_DETAIL. + * Note: Recognized only when MD_FLAG_ADMONITIONS is enabled. */ + MD_BLOCK_ADMONITION, + + /* A run of blank lines separating two blocks. Has no contents. + * Detail: Structure MD_BLOCK_BLANK_DETAIL. + * Note: Emitted only when MD_FLAG_PRESERVEBLANKLINES is enabled. */ + MD_BLOCK_BLANK +} MD_BLOCKTYPE; + +/* Span represents an in-line piece of a document which should be rendered with + * the same font, color and other attributes. A sequence of spans forms a block + * like paragraph or list item. */ +typedef enum MD_SPANTYPE { + /* ... */ + MD_SPAN_EM, + + /* ... */ + MD_SPAN_STRONG, + + /* ... + * Detail: Structure MD_SPAN_A_DETAIL. */ + MD_SPAN_A, + + /* ... + * Detail: Structure MD_SPAN_IMG_DETAIL. + * Note: Image text can contain nested spans and even nested images. + * If rendered into ALT attribute of HTML tag, it's responsibility + * of the parser to deal with it. + */ + MD_SPAN_IMG, + + /* ... */ + MD_SPAN_CODE, + + /* ... + * Syntax: ++insert++ + * Note: Recognized only when MD_FLAG_INSERT is enabled. */ + MD_SPAN_INS, + + /* ... + * Note: Recognized only when MD_FLAG_STRIKETHROUGH is enabled. + */ + MD_SPAN_DEL, + + /* For recognizing inline ($) and display ($$) equations + * Note: Recognized only when MD_FLAG_LATEXMATHSPANS is enabled. + */ + MD_SPAN_LATEXMATH, + MD_SPAN_LATEXMATH_DISPLAY, + + /* Wiki links + * Note: Recognized only when MD_FLAG_WIKILINKS is enabled. + */ + MD_SPAN_WIKILINK, + + /* ... + * Note: Recognized only when MD_FLAG_UNDERLINE is enabled. */ + MD_SPAN_U, + + /* Spoiler (hidden content revealed on interaction). + * Syntax: ||hidden text|| + * Note: Recognized only when MD_FLAG_SPOILERS is enabled. */ + MD_SPAN_SPOILER, + + /* ... + * Syntax: ^superscript^ + * Note: Recognized only when MD_FLAG_SUPERSCRIPTS is enabled. */ + MD_SPAN_SUPERSCRIPT, + + /* ... + * Syntax: ~subscript~ + * Note: Recognized only when MD_FLAG_SUBSCRIPTS is enabled. */ + MD_SPAN_SUBSCRIPT, + + /* Footnote reference, e.g. [^1] or [^note]. + * Syntax: [^label] + * Note: Recognized only when MD_FLAG_FOOTNOTES is enabled. + * The span is self-contained: no MD_TEXT callbacks fire between enter and + * leave. All needed information is in MD_SPAN_FOOTNOTE_REF_DETAIL. */ + MD_SPAN_FOOTNOTE_REF, + + /* ... + * Syntax: ==highlight== + * Note: Recognized only when MD_FLAG_HIGHLIGHT is enabled. */ + MD_SPAN_MARK +} MD_SPANTYPE; + +/* Text is the actual textual contents of span. */ +typedef enum MD_TEXTTYPE { + /* Normal text. */ + MD_TEXT_NORMAL = 0, + + /* NULL character. CommonMark requires replacing NULL character with + * the replacement char U+FFFD, so this allows caller to do that easily. */ + MD_TEXT_NULLCHAR, + + /* Line breaks. + * Note these are not sent from blocks with verbatim output (MD_BLOCK_CODE + * or MD_BLOCK_HTML). In such cases, '\n' is part of the text itself. */ + MD_TEXT_BR, /*
    (hard break) */ + MD_TEXT_SOFTBR, /* '\n' in source text where it is not semantically meaningful (soft break) */ + + /* Entity. + * (a) Named entity, e.g.   + * (Note MD4C does not have a list of known entities. + * Anything matching the regexp /&[A-Za-z][A-Za-z0-9]{1,47};/ is + * treated as a named entity.) + * (b) Numerical entity, e.g. Ӓ + * (c) Hexadecimal entity, e.g. ካ + * + * As MD4C is mostly encoding agnostic, application gets the verbatim + * entity text into the MD_PARSER::text_callback(). */ + MD_TEXT_ENTITY, + + /* Text in a code block (inside MD_BLOCK_CODE) or inlined code (`code`). + * If it is inside MD_BLOCK_CODE, it includes spaces for indentation and + * '\n' for new lines. MD_TEXT_BR and MD_TEXT_SOFTBR are not sent for this + * kind of text. */ + MD_TEXT_CODE, + + /* Text is a raw HTML. If it is contents of a raw HTML block (i.e. not + * an inline raw HTML), then MD_TEXT_BR and MD_TEXT_SOFTBR are not used. + * The text contains verbatim '\n' for the new lines. */ + MD_TEXT_HTML, + + /* Text is inside an equation. This is processed the same way as inlined code + * spans (`code`). */ + MD_TEXT_LATEXMATH +} MD_TEXTTYPE; + + +/* Alignment enumeration. */ +typedef enum MD_ALIGN { + MD_ALIGN_DEFAULT = 0, /* When unspecified. */ + MD_ALIGN_LEFT, + MD_ALIGN_CENTER, + MD_ALIGN_RIGHT +} MD_ALIGN; + + +/* String attribute. + * + * This wraps strings which are outside of a normal text flow and which are + * propagated within various detailed structures, but which still may contain + * string portions of different types like e.g. entities. + * + * So, for example, lets consider this image: + * + * ![image alt text](http://example.org/image.png 'foo " bar') + * + * The image alt text is propagated as a normal text via the MD_PARSER::text() + * callback. However, the image title ('foo " bar') is propagated as + * MD_ATTRIBUTE in MD_SPAN_IMG_DETAIL::title. + * + * Then the attribute MD_SPAN_IMG_DETAIL::title shall provide the following: + * -- [0]: "foo " (substr_types[0] == MD_TEXT_NORMAL; substr_offsets[0] == 0) + * -- [1]: """ (substr_types[1] == MD_TEXT_ENTITY; substr_offsets[1] == 4) + * -- [2]: " bar" (substr_types[2] == MD_TEXT_NORMAL; substr_offsets[2] == 10) + * -- [3]: (n/a) (n/a ; substr_offsets[3] == 14) + * + * Note that these invariants are always guaranteed: + * -- substr_offsets[0] == 0 + * -- substr_offsets[LAST+1] == size + * -- Currently, only MD_TEXT_NORMAL, MD_TEXT_ENTITY, MD_TEXT_NULLCHAR + * substrings can appear. This could change only of the specification + * changes. + */ +typedef struct MD_ATTRIBUTE { + const MD_CHAR* text; + MD_SIZE size; + const MD_TEXTTYPE* substr_types; + const MD_OFFSET* substr_offsets; +} MD_ATTRIBUTE; + + +/* Detailed info for MD_BLOCK_UL. */ +typedef struct MD_BLOCK_UL_DETAIL { + int is_tight; /* Non-zero if tight list, zero if loose. */ + MD_CHAR mark; /* Item bullet character in MarkDown source of the list, e.g. '-', '+', '*'. */ +} MD_BLOCK_UL_DETAIL; + +/* Detailed info for MD_BLOCK_OL. */ +typedef struct MD_BLOCK_OL_DETAIL { + unsigned start; /* Start index of the ordered list. */ + int is_tight; /* Non-zero if tight list, zero if loose. */ + MD_CHAR mark_delimiter; /* Character delimiting the item marks in MarkDown source, e.g. '.' or ')' */ +} MD_BLOCK_OL_DETAIL; + +/* Detailed info for MD_BLOCK_LI. */ +typedef struct MD_BLOCK_LI_DETAIL { + int is_task; /* Can be non-zero only with MD_FLAG_TASKLISTS */ + MD_CHAR task_mark; /* If is_task, then one of 'x', 'X' or ' '. Undefined otherwise. */ + MD_OFFSET task_mark_offset; /* If is_task, then offset in the input of the char between '[' and ']'. */ +} MD_BLOCK_LI_DETAIL; + +/* Detailed info for MD_BLOCK_H. */ +typedef struct MD_BLOCK_H_DETAIL { + unsigned level; /* Header level (1 - 6) */ +} MD_BLOCK_H_DETAIL; + +/* Detailed info for MD_BLOCK_CODE. */ +typedef struct MD_BLOCK_CODE_DETAIL { + MD_ATTRIBUTE info; + MD_ATTRIBUTE lang; + MD_CHAR fence_char; /* The character used for fenced code block; or zero for indented code block. */ +} MD_BLOCK_CODE_DETAIL; + +/* Detailed info for MD_BLOCK_TABLE. */ +typedef struct MD_BLOCK_TABLE_DETAIL { + unsigned col_count; /* Count of columns in the table. */ + unsigned head_row_count; /* Count of rows in the table header (currently always 1) */ + unsigned body_row_count; /* Count of rows in the table body */ +} MD_BLOCK_TABLE_DETAIL; + +/* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */ +typedef struct MD_BLOCK_TD_DETAIL { + MD_ALIGN align; +} MD_BLOCK_TD_DETAIL; + +/* Detailed info for MD_BLOCK_ADMONITION. */ +typedef struct MD_BLOCK_ADMONITION_DETAIL { + MD_ATTRIBUTE type; /* One of "note", "tip", "important", "warning", "caution" */ +} MD_BLOCK_ADMONITION_DETAIL; + +/* Detailed info for MD_SPAN_A. */ +typedef struct MD_SPAN_A_DETAIL { + MD_ATTRIBUTE href; + MD_ATTRIBUTE title; + int is_autolink; /* nonzero if this is an autolink */ +} MD_SPAN_A_DETAIL; + +/* Detailed info for MD_SPAN_IMG. */ +typedef struct MD_SPAN_IMG_DETAIL { + MD_ATTRIBUTE src; + MD_ATTRIBUTE title; +} MD_SPAN_IMG_DETAIL; + +/* Detailed info for MD_SPAN_WIKILINK. */ +typedef struct MD_SPAN_WIKILINK { + MD_ATTRIBUTE target; +} MD_SPAN_WIKILINK_DETAIL; + +/* Detailed info for MD_SPAN_FOOTNOTE_REF. */ +typedef struct MD_SPAN_FOOTNOTE_REF_DETAIL { + unsigned int id; /* 1-based identifier of the referenced footnote */ + unsigned int ref_id; /* 1-based identifier of this reference among references to the same footnote */ + MD_ATTRIBUTE label; /* Raw label text, e.g. "1" or "note" */ +} MD_SPAN_FOOTNOTE_REF_DETAIL; + +/* Detailed info for MD_BLOCK_FOOTNOTE_DEF. */ +typedef struct MD_BLOCK_FOOTNOTE_DEF_DETAIL { + unsigned int id; /* 1-based identifier of this footnote */ + unsigned int ref_count; /* Number of references to this footnote */ + MD_ATTRIBUTE label; /* Raw label text */ +} MD_BLOCK_FOOTNOTE_DEF_DETAIL; + +/* Detailed info for MD_BLOCK_BLANK. */ +typedef struct MD_BLOCK_BLANK_DETAIL { + unsigned line_count; /* Count of blank lines forming the block separation */ +} MD_BLOCK_BLANK_DETAIL; + +/* Flags specifying extensions/deviations from CommonMark specification. + * + * By default (when MD_PARSER::flags == 0), we follow CommonMark specification. + * The following flags may allow some extensions or deviations from it. + */ +#define MD_FLAG_COLLAPSEWHITESPACE 0x1 /* In MD_TEXT_NORMAL, collapse non-trivial whitespace into single ' ' */ +#define MD_FLAG_PERMISSIVEATXHEADERS 0x2 /* Do not require space in ATX headers ( ###header ) */ +#define MD_FLAG_PERMISSIVEURLAUTOLINKS 0x4 /* Recognize URLs as autolinks even without '<', '>' */ +#define MD_FLAG_PERMISSIVEEMAILAUTOLINKS 0x8 /* Recognize e-mails as autolinks even without '<', '>' and 'mailto:' */ +#define MD_FLAG_NOINDENTEDCODEBLOCKS 0x10 /* Disable indented code blocks. (Only fenced code works.) */ +#define MD_FLAG_NOHTMLBLOCKS 0x20 /* Disable raw HTML blocks. */ +#define MD_FLAG_NOHTMLSPANS 0x40 /* Disable raw HTML (inline). */ +#define MD_FLAG_TABLES 0x100 /* Enable tables extension. */ +#define MD_FLAG_STRIKETHROUGH 0x200 /* Enable strikethrough extension. */ +#define MD_FLAG_PERMISSIVEWWWAUTOLINKS 0x400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */ +#define MD_FLAG_TASKLISTS 0x800 /* Enable task list extension. */ +#define MD_FLAG_LATEXMATHSPANS 0x1000 /* Enable $ and $$ containing LaTeX equations. */ +#define MD_FLAG_WIKILINKS 0x2000 /* Enable wiki links extension. */ +#define MD_FLAG_UNDERLINE 0x4000 /* Enable underline extension (and disables '_' for normal emphasis). */ +#define MD_FLAG_HARD_SOFT_BREAKS 0x8000 /* Force all soft breaks to act as hard breaks. */ +#define MD_FLAG_SPOILERS 0x10000 /* Enable ||hidden text|| spoiler spans. */ +#define MD_FLAG_SUPERSCRIPTS 0x20000 /* Enable ^superscript^ spans. */ +#define MD_FLAG_SUBSCRIPTS 0x40000 /* Enable ~subscript~ spans. */ +#define MD_FLAG_ADMONITIONS 0x80000 /* Enable admonitions extension. */ +#define MD_FLAG_FOOTNOTES 0x100000 /* Enable [^label] footnote references. */ +#define MD_FLAG_HIGHLIGHT 0x200000 /* Enable ==highlight== spans. */ +#define MD_FLAG_PRESERVEBLANKLINES 0x400000 /* Report blank line runs as MD_BLOCK_BLANK. */ +#define MD_FLAG_INSERT 0x800000 /* Enable insert extension. */ + +#define MD_FLAG_PERMISSIVEAUTOLINKS (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS) +#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS) + +/* Convenient sets of flags corresponding to well-known Markdown dialects. + * + * Note we may only support subset of features of the referred dialect. + * The constant just enables those extensions which bring us as close as + * possible given what features we implement. + * + * ABI compatibility note: Meaning of these can change in time as new + * extensions, bringing the dialect closer to the original, are implemented. + */ +#define MD_DIALECT_COMMONMARK 0 +#define MD_DIALECT_GITHUB (MD_FLAG_PERMISSIVEAUTOLINKS | MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_TASKLISTS | MD_FLAG_ADMONITIONS | MD_FLAG_FOOTNOTES) + +/* Parser structure. + */ +typedef struct MD_PARSER { + /* Reserved. Set to zero. + */ + unsigned abi_version; + + /* Dialect options. Bitmask of MD_FLAG_xxxx values. + */ + unsigned flags; + + /* Caller-provided rendering callbacks. + * + * For some block/span types, more detailed information is provided in a + * type-specific structure pointed by the argument 'detail'. + * + * The last argument of all callbacks, 'userdata', is just propagated from + * md_parse() and is available for any use by the application. + * + * Note any strings provided to the callbacks as their arguments or as + * members of any detail structure are generally not zero-terminated. + * Application has to take the respective size information into account. + * + * Any rendering callback may abort further parsing of the document by + * returning non-zero. + */ + int (*enter_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + int (*leave_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + + int (*enter_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + int (*leave_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + + int (*text)(MD_TEXTTYPE /*type*/, const MD_CHAR* /*text*/, MD_SIZE /*size*/, void* /*userdata*/); + + /* Debug callback. Optional (may be NULL). + * + * If provided and something goes wrong, this function gets called. + * This is intended for debugging and problem diagnosis for developers; + * it is not intended to provide any errors suitable for displaying to an + * end user. + */ + void (*debug_log)(const char* /*msg*/, void* /*userdata*/); + + /* Reserved. Set to NULL. + */ + void (*syntax)(void); +} MD_PARSER; + + +/* For backward compatibility. Do not use in new code. + */ +typedef MD_PARSER MD_RENDERER; + + +/* Parse the Markdown document stored in the string 'text' of size 'size'. + * The parser provides callbacks to be called during the parsing so the + * caller can render the document on the screen or convert the Markdown + * to another format. + * + * Zero is returned on success. If a runtime error occurs (e.g. a memory + * fails), -1 is returned. If the processing is aborted due any callback + * returning non-zero, the return value of the callback is returned. + */ +int md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata); + + +#ifdef __cplusplus + } /* extern "C" { */ +#endif + +#endif /* MD4C_H */ diff --git a/include/Mw/Milsko.h b/include/Mw/Milsko.h index abdc073..6d35d54 100644 --- a/include/Mw/Milsko.h +++ b/include/Mw/Milsko.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index d820ea4..71b8f5f 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -58,6 +58,7 @@ #define MwNminute "Iminute" #define MwNsecond "Isecond" #define MwNtype "Itype" +#define MwNautoResize "IautoResize" #define MwNtitle "Stitle" #define MwNtext "Stext" diff --git a/include/Mw/Widget/Document.h b/include/Mw/Widget/Document.h new file mode 100644 index 0000000..5b38af4 --- /dev/null +++ b/include/Mw/Widget/Document.h @@ -0,0 +1,24 @@ +/*! + * @file Mw/Widget/Document.h + * @brief Document widget + */ +#ifndef __MW_WIDGET_DOCUMENT_H__ +#define __MW_WIDGET_DOCUMENT_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @brief Clock widget class + */ +MWDECL MwClass MwDocumentClass; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/milsko.xml b/milsko.xml index 084f825..ec30e82 100644 --- a/milsko.xml +++ b/milsko.xml @@ -111,6 +111,7 @@ + diff --git a/pl/rules.pl b/pl/rules.pl index 9d2081c..ad62d6c 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -155,6 +155,7 @@ new_object("src/widget/checkbox.c"); new_object("src/widget/chart.c"); new_object("src/widget/clock.c"); new_object("src/widget/combobox.c"); +new_object("src/widget/document.c"); new_object("src/widget/entry.c"); new_object("src/widget/frame.c"); new_object("src/widget/image.c"); @@ -212,6 +213,7 @@ new_example("examples/basic/filechooser"); new_example("examples/basic/periodic"); new_example("examples/basic/subwindow"); new_example("examples/basic/tab"); +new_example("examples/basic/document"); if (param_get("opengl")) { new_example("examples/gldemos/boing", $gl_libs); diff --git a/src/widget/document.c b/src/widget/document.c new file mode 100644 index 0000000..4c5414a --- /dev/null +++ b/src/widget/document.c @@ -0,0 +1,54 @@ +#include + +#include "../../external/md4c.h" + +static int wcreate(MwWidget handle) { + MwSetDefault(handle); + + return 0; +} + +static void draw(MwWidget handle) { + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwRect r; + + r.x = 0; + r.y = 0; + r.width = MwGetInteger(handle, MwNwidth); + r.height = MwGetInteger(handle, MwNheight); + MwDrawRect(handle, &r, base); + + MwLLFreeColor(base); +} + +static void prop_change(MwWidget handle, const char* key) { + if(strcmp(key, MwNautoResize) == 0 || strcmp(key, MwNtext) == 0) MwForceRender(handle); + + if(strcmp(key, MwNtext) == 0) { + MD_PARSER parser; + memset(&parser, 0, sizeof(parser)); + } +} + +MwClassRec MwDocumentClassRec = { + wcreate, /* create */ + NULL, /* destroy */ + draw, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + NULL, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ + NULL, + NULL, + NULL}; +MwClass MwDocumentClass = &MwDocumentClassRec; diff --git a/tools/genmk.pl b/tools/genmk.pl index 689e09e..26a7ebb 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -230,6 +230,6 @@ scan_examples("examples/gldemos"); @examples = sort(@examples); -generate("BorMakefile", "Borland"); +#generate("BorMakefile", "Borland"); generate("NTMakefile", "MSVC"); generate("WatMakefile", "Watcom"); From c1ab3af1c1e94c4ec7c914419fed2052b609752c Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 05:19:37 +0900 Subject: [PATCH 089/168] ok --- external/md4c.c | 3 +-- src/backend/gdi.c | 7 ++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/external/md4c.c b/external/md4c.c index 22ab420..73c7b5d 100644 --- a/external/md4c.c +++ b/external/md4c.c @@ -24,7 +24,6 @@ */ #include -#include #include #include #include @@ -5840,7 +5839,7 @@ md_consume_link_reference_definitions(MD_CTX* ctx) MD_LINE* lines = (MD_LINE*) (ctx->current_block + 1); MD_SIZE n_lines = ctx->current_block->n_lines; MD_SIZE n = 0; - bool inject_hr = false; + int inject_hr = 0; OFF ignored; while(n < n_lines) { diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 660a0fc..2013b9a 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -178,13 +178,14 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { for(i = 0; i < count; i++) { wchar_t wpath[MAX_PATH]; - char path[MAX_PATH]; + char* path; wsymtbl.DragQueryFileW(hDrop, i, wpath, MAX_PATH); - memset(path, 0, sizeof(path)); - WideCharToMultiByte(CP_UTF8, 0, wpath, -1, path, sizeof(path) - 1, NULL, NULL); + path = MwUTF16TextToUTF8Text(wpath); MwLLDispatch(u->ll, drag_and_drop, path); + + free(path); } wsymtbl.DragFinish(hDrop); break; From cbcf3c5ef185d38fca51bf6a6aba6261db9667ce Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 05:21:38 +0900 Subject: [PATCH 090/168] ok --- NTMakefile | 12 ++++++++++-- WatMakefile | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/NTMakefile b/NTMakefile index d0fc463..26723bc 100644 --- a/NTMakefile +++ b/NTMakefile @@ -6,9 +6,9 @@ MW_LDFLAGS = /DLL EXE_CFLAGS = /Iinclude EXE_LDFLAGS = .SUFFIXES: .obj .c -all: src\Mw.dll examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe +all: src\Mw.dll examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\document.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe lib: src\Mw.dll -examples: examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe +examples: examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\document.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe clean: del /f /q external\libz\src\adler32.obj del /f /q external\libz\src\compress.obj @@ -112,6 +112,7 @@ clean: del /f /q examples\basic\clipboard.obj del /f /q examples\basic\colorpicker.obj del /f /q examples\basic\combobox.obj + del /f /q examples\basic\document.obj del /f /q examples\basic\example.obj del /f /q examples\basic\filechooser.obj del /f /q examples\basic\image.obj @@ -139,6 +140,7 @@ clean: del /f /q examples\basic\clipboard.exe del /f /q examples\basic\colorpicker.exe del /f /q examples\basic\combobox.exe + del /f /q examples\basic\document.exe del /f /q examples\basic\example.exe del /f /q examples\basic\filechooser.exe del /f /q examples\basic\image.exe @@ -197,6 +199,12 @@ examples\basic\combobox.exe: examples\basic\combobox.obj src\Mw.dll examples\basic\combobox.obj: examples/basic/combobox.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/combobox.c +examples\basic\document.exe: examples\basic\document.obj src\Mw.dll + $(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\document.obj src\Mw.lib + +examples\basic\document.obj: examples/basic/document.c + $(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/document.c + examples\basic\example.exe: examples\basic\example.obj src\Mw.dll $(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\example.obj src\Mw.lib diff --git a/WatMakefile b/WatMakefile index ce6792b..7924e17 100644 --- a/WatMakefile +++ b/WatMakefile @@ -5,9 +5,9 @@ MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -d MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt -all: src/Mw.dll examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe +all: src/Mw.dll examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe lib: src/Mw.dll -examples: examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe +examples: examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe clean: .SYMBOLIC %erase external/libz/src/adler32.obj %erase external/libz/src/compress.obj @@ -111,6 +111,7 @@ clean: .SYMBOLIC %erase examples/basic/clipboard.obj %erase examples/basic/colorpicker.obj %erase examples/basic/combobox.obj + %erase examples/basic/document.obj %erase examples/basic/example.obj %erase examples/basic/filechooser.obj %erase examples/basic/image.obj @@ -138,6 +139,7 @@ clean: .SYMBOLIC %erase examples/basic/clipboard.exe %erase examples/basic/colorpicker.exe %erase examples/basic/combobox.exe + %erase examples/basic/document.exe %erase examples/basic/example.exe %erase examples/basic/filechooser.exe %erase examples/basic/image.exe @@ -196,6 +198,12 @@ examples/basic/combobox.exe: examples/basic/combobox.obj src/Mw.dll examples/basic/combobox.obj: examples/basic/combobox.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/combobox.c +examples/basic/document.exe: examples/basic/document.obj src/Mw.dll + $(LD) $(EXE_LDFLAGS) name $@ file examples/basic/document.obj library clib3r.lib library src/Mw.lib + +examples/basic/document.obj: examples/basic/document.c + $(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/document.c + examples/basic/example.exe: examples/basic/example.obj src/Mw.dll $(LD) $(EXE_LDFLAGS) name $@ file examples/basic/example.obj library clib3r.lib library src/Mw.lib From 1d39b6584db19de6ef0d29ee99a4be1213d05f0f Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 05:22:23 +0900 Subject: [PATCH 091/168] ok --- external/md4c.c | 444 ++++++++++++++++++++++++------------------------ 1 file changed, 222 insertions(+), 222 deletions(-) diff --git a/external/md4c.c b/external/md4c.c index 73c7b5d..8665a14 100644 --- a/external/md4c.c +++ b/external/md4c.c @@ -176,7 +176,7 @@ struct MD_CTX_tag { MD_PARSER parser; void* userdata; - /* When this is true, it allows some optimizations. */ + /* When this is 1, it allows some optimizations. */ int doc_ends_with_newline; /* Helper temporary growing buffer. */ @@ -384,9 +384,9 @@ md_ascii_case_eq(const CHAR* s1, const CHAR* s2, SZ n) if(ISLOWER_(ch2)) ch2 += ('A'-'a'); if(ch1 != ch2) - return false; + return 0; } - return true; + return 1; } static inline int @@ -1107,7 +1107,7 @@ md_is_html_tag(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF MD_ASSERT(CH(beg) == _T('<')); if(off + 1 >= line_end) - return false; + return 0; off++; /* For parsing attributes, we need a little state automaton below. @@ -1130,7 +1130,7 @@ md_is_html_tag(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF /* Tag name */ if(off >= line_end || !ISALPHA(off)) - return false; + return 0; off++; while(off < line_end && (ISALNUM(off) || CH(off) == _T('-'))) off++; @@ -1179,22 +1179,22 @@ md_is_html_tag(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF else if(!ISANYOF(off, _T("\"'=<>`")) && !ISNEWLINE(off)) attr_state = 41; else - return false; + return 0; off++; } else { /* Anything unexpected. */ - return false; + return 0; } } /* We have to be on a single line. See definition of start condition * of HTML block, type 7. */ if(n_lines == 0) - return false; + return 0; line_index++; if(line_index >= n_lines) - return false; + return 0; off = lines[line_index].beg; line_end = lines[line_index].end; @@ -1203,15 +1203,15 @@ md_is_html_tag(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF attr_state = 1; if(off >= max_end) - return false; + return 0; } done: if(off >= max_end) - return false; + return 0; *p_end = off+1; - return true; + return 1; } static int @@ -1226,15 +1226,15 @@ md_scan_for_html_closer(MD_CTX* ctx, const MD_CHAR* str, MD_SIZE len, if(off < *p_scan_horizon && *p_scan_horizon >= max_end - len) { /* We have already scanned the range up to the max_end so we know * there is nothing to see. */ - return false; + return 0; } - while(true) { + while(1) { while(off + len <= lines[line_index].end && off + len <= max_end) { if(md_ascii_eq(STR(off), str, len)) { /* Success. */ *p_end = off + len; - return true; + return 1; } off++; } @@ -1243,7 +1243,7 @@ md_scan_for_html_closer(MD_CTX* ctx, const MD_CHAR* str, MD_SIZE len, if(off >= max_end || line_index >= n_lines) { /* Failure. */ *p_scan_horizon = off; - return false; + return 0; } off = lines[line_index].beg; @@ -1258,9 +1258,9 @@ md_is_html_comment(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, MD_ASSERT(CH(beg) == _T('<')); if(off + 4 >= lines[0].end) - return false; + return 0; if(CH(off+1) != _T('!') || CH(off+2) != _T('-') || CH(off+3) != _T('-')) - return false; + return 0; /* Skip only "" or "" */ off += 2; @@ -1276,9 +1276,9 @@ md_is_html_processing_instruction(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_l OFF off = beg; if(off + 2 >= lines[0].end) - return false; + return 0; if(CH(off+1) != _T('?')) - return false; + return 0; off += 2; return md_scan_for_html_closer(ctx, _T("?>"), 2, @@ -1291,14 +1291,14 @@ md_is_html_declaration(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF b OFF off = beg; if(off + 2 >= lines[0].end) - return false; + return 0; if(CH(off+1) != _T('!')) - return false; + return 0; off += 2; /* Declaration name. */ if(off >= lines[0].end || !ISALPHA(off)) - return false; + return 0; off++; while(off < lines[0].end && ISALPHA(off)) off++; @@ -1316,9 +1316,9 @@ md_is_html_cdata(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OF OFF off = beg; if(off + open_size >= lines[0].end) - return false; + return 0; if(memcmp(STR(off), open_str, open_size * sizeof(CHAR)) != 0) - return false; + return 0; off += open_size; return md_scan_for_html_closer(ctx, _T("]]>"), 3, @@ -1352,9 +1352,9 @@ md_is_hex_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, O if(1 <= off - beg && off - beg <= 6) { *p_end = off; - return true; + return 1; } else { - return false; + return 0; } } @@ -1369,9 +1369,9 @@ md_is_dec_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, O if(1 <= off - beg && off - beg <= 7) { *p_end = off; - return true; + return 1; } else { - return false; + return 0; } } @@ -1384,16 +1384,16 @@ md_is_named_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, if(off < max_end && ISALPHA_(text[off])) off++; else - return false; + return 0; while(off < max_end && ISALNUM_(text[off]) && off - beg <= 48) off++; if(2 <= off - beg && off - beg <= 48) { *p_end = off; - return true; + return 1; } else { - return false; + return 0; } } @@ -1415,9 +1415,9 @@ md_is_entity_str(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end if(is_contents && off < max_end && text[off] == _T(';')) { *p_end = off+1; - return true; + return 1; } else { - return false; + return 0; } } @@ -1517,10 +1517,10 @@ md_build_attribute(MD_CTX* ctx, const CHAR* raw_text, SZ raw_size, /* If there is no backslash and no ampersand, build trivial attribute * without any malloc(). */ - is_trivial = true; + is_trivial = 1; for(raw_off = 0; raw_off < raw_size; raw_off++) { if(ISANYOF3_(raw_text[raw_off], _T('\\'), _T('&'), _T('\0'))) { - is_trivial = false; + is_trivial = 0; break; } } @@ -1623,7 +1623,7 @@ md_label_hash(const CHAR* label, SZ size) unsigned hash = MD_FNV1A_BASE; OFF off; unsigned codepoint; - int is_whitespace = false; + int is_whitespace = 0; off = md_skip_unicode_whitespace(label, 0, size); while(off < size) { @@ -1761,7 +1761,7 @@ static int md_is_complex_label_bucket(MD_LABEL_HASH_TABLE* table, void* bucket) { if(bucket == NULL) - return false; + return 0; return (MD_LABEL_HASH_ENTRY*) bucket < (MD_LABEL_HASH_ENTRY*) table->defs || (MD_LABEL_HASH_ENTRY*) bucket >= (MD_LABEL_HASH_ENTRY*)((char*)table->defs + table->n_defs * table->def_size); @@ -2031,9 +2031,9 @@ md_is_footnote_label(MD_CTX* ctx, OFF beg, OFF* p_end) if(end - beg > 0 && end < ctx->size && CH(end) == _T(']')) { if(p_end != NULL) *p_end = end; - return true; + return 1; } else { - return false; + return 0; } } @@ -2061,17 +2061,17 @@ md_is_footnote_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) label_beg = off; if(!md_is_footnote_label(ctx, label_beg, &off)) - return false; + return 0; label_end = off; /* Closing bracket. */ if(off >= lines[0].end || CH(off) != _T(']')) - return false; + return 0; off++; /* Colon. */ if(off >= lines[0].end || CH(off) != _T(':')) - return false; + return 0; off++; /* Skip optional whitespace after colon on the first line. */ @@ -2199,7 +2199,7 @@ md_is_link_label(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, *p_beg_line_index = 0; if(CH(off) != _T('[')) - return false; + return 0; off++; while(1) { @@ -2214,7 +2214,7 @@ md_is_link_label(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, contents_end = off + 2; off += 2; } else if(CH(off) == _T('[')) { - return false; + return 0; } else if(CH(off) == _T(']')) { if(contents_beg < contents_end) { /* Success. */ @@ -2222,10 +2222,10 @@ md_is_link_label(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, *p_contents_end = contents_end; *p_end = off+1; *p_end_line_index = line_index; - return true; + return 1; } else { /* Link label must have some non-whitespace contents. */ - return false; + return 0; } } else { unsigned codepoint; @@ -2245,7 +2245,7 @@ md_is_link_label(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, len++; if(len > 999) - return false; + return 0; } line_index++; @@ -2256,7 +2256,7 @@ md_is_link_label(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, break; } - return false; + return 0; } static int @@ -2266,7 +2266,7 @@ md_is_link_destination_A(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, OFF off = beg; if(off >= max_end || CH(off) != _T('<')) - return false; + return 0; off++; while(off < max_end) { @@ -2276,20 +2276,20 @@ md_is_link_destination_A(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, } if(ISNEWLINE(off) || CH(off) == _T('<')) - return false; + return 0; if(CH(off) == _T('>')) { /* Success. */ *p_contents_beg = beg+1; *p_contents_end = off; *p_end = off+1; - return true; + return 1; } off++; } - return false; + return 0; } static int @@ -2314,7 +2314,7 @@ md_is_link_destination_B(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, if(CH(off) == _T('(')) { parenthesis_level++; if(parenthesis_level > 32) - return false; + return 0; } else if(CH(off) == _T(')')) { if(parenthesis_level == 0) break; @@ -2325,13 +2325,13 @@ md_is_link_destination_B(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, } if(parenthesis_level != 0 || off == beg) - return false; + return 0; /* Success. */ *p_contents_beg = beg; *p_contents_end = off; *p_end = off; - return true; + return 1; } static inline int @@ -2359,11 +2359,11 @@ md_is_link_title(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, if(off >= lines[line_index].end) { line_index++; if(line_index >= n_lines) - return false; + return 0; off = lines[line_index].beg; } if(off == beg) - return false; + return 0; *p_beg_line_index = line_index; @@ -2372,7 +2372,7 @@ md_is_link_title(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, case _T('"'): closer_char = _T('"'); break; case _T('\''): closer_char = _T('\''); break; case _T('('): closer_char = _T(')'); break; - default: return false; + default: return 0; } off++; @@ -2389,10 +2389,10 @@ md_is_link_title(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, *p_contents_end = off; *p_end = off+1; *p_end_line_index = line_index; - return true; + return 1; } else if(closer_char == _T(')') && CH(off) == _T('(')) { /* ()-style title cannot contain (unescaped '(')) */ - return false; + return 0; } off++; @@ -2401,7 +2401,7 @@ md_is_link_title(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, line_index++; } - return false; + return 0; } /* Returns 0 if it is not a reference definition. @@ -2418,13 +2418,13 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lin OFF label_contents_beg; OFF label_contents_end; MD_SIZE label_contents_line_index; - int label_is_multiline = false; + int label_is_multiline = 0; OFF dest_contents_beg; OFF dest_contents_end; OFF title_contents_beg; OFF title_contents_end; MD_SIZE title_contents_line_index; - int title_is_multiline = false; + int title_is_multiline = 0; OFF off; MD_SIZE line_index = 0; MD_SIZE tmp_line_index; @@ -2435,12 +2435,12 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lin if(!md_is_link_label(ctx, lines, n_lines, lines[0].beg, &off, &label_contents_line_index, &line_index, &label_contents_beg, &label_contents_end)) - return false; + return 0; label_is_multiline = (label_contents_line_index != line_index); /* Colon. */ if(off >= lines[line_index].end || CH(off) != _T(':')) - return false; + return 0; off++; /* Optional white space with up to one line break. */ @@ -2449,14 +2449,14 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lin if(off >= lines[line_index].end) { line_index++; if(line_index >= n_lines) - return false; + return 0; off = lines[line_index].beg; } /* Link destination. */ if(!md_is_link_destination(ctx, off, lines[line_index].end, &off, &dest_contents_beg, &dest_contents_end)) - return false; + return 0; /* (Optional) title. Note we interpret it as an title only if nothing * more follows on its last line. */ @@ -2470,7 +2470,7 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lin line_index += tmp_line_index; } else { /* Not a title. */ - title_is_multiline = false; + title_is_multiline = 0; title_contents_beg = off; title_contents_end = off; title_contents_line_index = 0; @@ -2478,7 +2478,7 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lin /* Nothing more can follow on the last line. */ if(off < lines[line_index].end) - return false; + return 0; if(label_is_multiline) { CHAR* label; @@ -2493,7 +2493,7 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lin free(label); goto abort; } - def->label_needs_free = true; + def->label_needs_free = 1; } else { def = (MD_REF_DEF*) md_add_label_def(ctx, &ctx->ref_def_hashtable, STR(label_contents_beg), label_contents_end - label_contents_beg); @@ -2507,7 +2507,7 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lin MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end, lines + title_contents_line_index, n_lines - title_contents_line_index, _T('\n'), &def->title, &def->title_size)); - def->title_needs_free = true; + def->title_needs_free = 1; } else { def->title = (CHAR*) STR(title_contents_beg); def->title_size = title_contents_end - title_contents_beg; @@ -2535,13 +2535,13 @@ md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int is_multiline; CHAR* label; SZ label_size; - int ret = false; + int ret = 0; MD_ASSERT(CH(beg) == _T('[') || CH(beg) == _T('!')); MD_ASSERT(CH(end-1) == _T(']')); if(ctx->max_ref_def_output == 0) - return false; + return 0; beg += (CH(beg) == _T('!') ? 2 : 1); end--; @@ -2564,7 +2564,7 @@ md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, attr->dest_end = def->dest_end; attr->title = def->title; attr->title_size = def->title_size; - attr->title_needs_free = false; + attr->title_needs_free = 0; } if(is_multiline) @@ -2575,7 +2575,7 @@ md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, MD_SIZE output_size_estimation = def->entry.label_size + def->title_size + def->dest_end - def->dest_beg; if(output_size_estimation < ctx->max_ref_def_output) { ctx->max_ref_def_output -= output_size_estimation; - ret = true; + ret = 1; } else { MD_LOG("Too many link reference definition instantiations."); ctx->max_ref_def_output = 0; @@ -2597,7 +2597,7 @@ md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, MD_SIZE title_contents_line_index; int title_is_multiline; OFF off = beg; - int ret = false; + int ret = 0; md_lookup_line(off, lines, n_lines, &line_index); @@ -2610,7 +2610,7 @@ md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, if(off >= lines[line_index].end && (off >= ctx->size || ISNEWLINE(off))) { line_index++; if(line_index >= n_lines) - return false; + return 0; off = lines[line_index].beg; } @@ -2620,16 +2620,16 @@ md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, attr->dest_end = off; attr->title = NULL; attr->title_size = 0; - attr->title_needs_free = false; + attr->title_needs_free = 0; off++; *p_end = off; - return true; + return 1; } /* Link destination. */ if(!md_is_link_destination(ctx, off, lines[line_index].end, &off, &attr->dest_beg, &attr->dest_end)) - return false; + return 0; /* (Optional) title. */ if(md_is_link_title(ctx, lines + line_index, n_lines - line_index, off, @@ -2641,7 +2641,7 @@ md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, line_index += tmp_line_index; } else { /* Not a title. */ - title_is_multiline = false; + title_is_multiline = 0; title_contents_beg = off; title_contents_end = off; title_contents_line_index = 0; @@ -2653,7 +2653,7 @@ md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, if(off >= lines[line_index].end) { line_index++; if(line_index >= n_lines) - return false; + return 0; off = lines[line_index].beg; } if(CH(off) != _T(')')) @@ -2663,20 +2663,20 @@ md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, if(title_contents_beg >= title_contents_end) { attr->title = NULL; attr->title_size = 0; - attr->title_needs_free = false; + attr->title_needs_free = 0; } else if(!title_is_multiline) { attr->title = (CHAR*) STR(title_contents_beg); attr->title_size = title_contents_end - title_contents_beg; - attr->title_needs_free = false; + attr->title_needs_free = 0; } else { MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end, lines + title_contents_line_index, n_lines - title_contents_line_index, _T('\n'), &attr->title, &attr->title_size)); - attr->title_needs_free = true; + attr->title_needs_free = 1; } *p_end = off; - ret = true; + ret = 1; abort: return ret; @@ -3036,11 +3036,11 @@ md_is_code_span(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF closer_end; SZ mark_len; OFF line_end; - int has_space_after_opener = false; - int has_eol_after_opener = false; - int has_space_before_closer = false; - int has_eol_before_closer = false; - int has_only_space = true; + int has_space_after_opener = 0; + int has_eol_after_opener = 0; + int has_space_before_closer = 0; + int has_eol_before_closer = 0; + int has_only_space = 1; MD_SIZE line_index = 0; line_end = lines[0].end; @@ -3055,22 +3055,22 @@ md_is_code_span(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, mark_len = opener_end - opener_beg; if(mark_len > CODESPAN_MARK_MAXLEN) - return false; + return 0; /* Check whether we already know there is no closer of this length. * If so, re-scan does no sense. This fixes issue #59. */ if(last_potential_closers[mark_len-1] >= lines[n_lines-1].end || (*p_reached_paragraph_end && last_potential_closers[mark_len-1] < opener_end)) - return false; + return 0; closer_beg = opener_end; closer_end = opener_end; /* Find closer mark. */ - while(true) { + while(1) { while(closer_beg < line_end && CH(closer_beg) != _T('`')) { if(CH(closer_beg) != _T(' ')) - has_only_space = false; + has_only_space = 0; closer_beg++; } closer_end = closer_beg; @@ -3086,7 +3086,7 @@ md_is_code_span(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, if(closer_end - closer_beg > 0) { /* We have found a back-tick which is not part of the closer. */ - has_only_space = false; + has_only_space = 0; /* But if we eventually fail, remember it as a potential closer * of its own length for future attempts. This mitigates needs for @@ -3101,8 +3101,8 @@ md_is_code_span(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, line_index++; if(line_index >= n_lines) { /* Reached end of the paragraph and still nothing. */ - *p_reached_paragraph_end = true; - return false; + *p_reached_paragraph_end = 1; + return 0; } /* Try on the next line. */ line_end = lines[line_index].end; @@ -3143,7 +3143,7 @@ md_is_code_span(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, closer->beg = closer_beg; closer->end = closer_end; closer->flags = MD_MARK_POTENTIAL_CLOSER; - return true; + return 1; } static int @@ -3155,33 +3155,33 @@ md_is_autolink_uri(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end) /* Check for scheme. */ if(off >= max_end || !ISALNUM(off)) - return false; + return 0; off++; while(1) { if(off >= max_end) - return false; + return 0; if(off - beg > 32) - return false; + return 0; if(CH(off) == _T(':') && off - beg >= 3) break; if(!ISALNUM(off) && CH(off) != _T('+') && CH(off) != _T('-') && CH(off) != _T('.')) - return false; + return 0; off++; } /* Check the path after the scheme. */ while(off < max_end && CH(off) != _T('>')) { if(ISWHITESPACE(off) || ISCNTRL(off) || CH(off) == _T('<')) - return false; + return 0; off++; } if(off >= max_end) - return false; + return 0; MD_ASSERT(CH(off) == _T('>')); *p_end = off+1; - return true; + return 1; } static int @@ -3202,11 +3202,11 @@ md_is_autolink_email(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end) while(off < max_end && (ISALNUM(off) || ISANYOF(off, _T(".!#$%&'*+/=?^_`{|}~-")))) off++; if(off <= beg+1) - return false; + return 0; /* '@' */ if(off >= max_end || CH(off) != _T('@')) - return false; + return 0; off++; /* Labels delimited with '.'; each label is sequence of 1 - 63 alnum @@ -3223,32 +3223,32 @@ md_is_autolink_email(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end) break; if(label_len > 63) - return false; + return 0; off++; } if(label_len <= 0 || off >= max_end || CH(off) != _T('>') || CH(off-1) == _T('-')) - return false; + return 0; *p_end = off+1; - return true; + return 1; } static int md_is_autolink(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, int* p_missing_mailto) { if(md_is_autolink_uri(ctx, beg, max_end, p_end)) { - *p_missing_mailto = false; - return true; + *p_missing_mailto = 0; + return 1; } if(md_is_autolink_email(ctx, beg, max_end, p_end)) { - *p_missing_mailto = true; - return true; + *p_missing_mailto = 1; + return 1; } - return false; + return 0; } static int @@ -3258,13 +3258,13 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int table_m int ret = 0; MD_MARK* mark; OFF codespan_last_potential_closers[CODESPAN_MARK_MAXLEN] = { 0 }; - int codespan_scanned_till_paragraph_end = false; + int codespan_scanned_till_paragraph_end = 0; for(line_index = 0; line_index < n_lines; line_index++) { const MD_LINE* line = &lines[line_index]; OFF off = line->beg; - while(true) { + while(1) { CHAR ch; #ifdef MD4C_USE_UTF16 @@ -3776,7 +3776,7 @@ static void md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE /* Try to resolve a bracket pair as a wiki link '[[destination]]' or * '[[destination|label]]'. - * Returns true if resolved, false if not a wiki link, -1 on error. */ + * Returns 1 if resolved, 0 if not a wiki link, -1 on error. */ static int md_resolve_bracket_wikilink(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int opener_index, int closer_index, @@ -3791,16 +3791,16 @@ md_resolve_bracket_wikilink(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF off; if(!(ctx->parser.flags & MD_FLAG_WIKILINKS)) - return false; + return 0; if(opener->ch != _T('[') || opener->end - opener->beg != 1 || next_opener == NULL || next_opener->ch != _T('[') || next_opener->end - next_opener->beg != 1 || next_closer == NULL || next_closer->ch != _T(']') || next_closer->end - next_closer->beg != 1) - return false; + return 0; /* Check that the next_opener and next_closer are nested properly. */ if(next_opener->beg != opener->beg - 1 || next_closer->beg != closer->beg + 1) - return false; + return 0; /* We don't allow destination to be longer than 100 characters. * Lets scan to see whether there is '|'. (If not then the whole @@ -3824,12 +3824,12 @@ md_resolve_bracket_wikilink(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, dest_beg = opener->end; dest_end = (delim != NULL) ? delim->beg : closer->beg; if(dest_end - dest_beg == 0 || dest_end - dest_beg > 100) - return false; + return 0; /* There may not be any new line in the destination. */ for(off = dest_beg; off < dest_end; off++) { if(ISNEWLINE(off)) - return false; + return 0; } md_pop_openers(ctx, opener_index); @@ -3857,7 +3857,7 @@ md_resolve_bracket_wikilink(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, md_analyze_link_contents(ctx, lines, n_lines, delim_index+1, closer_index); *p_opener_index = next_opener->prev; - return true; + return 1; } /* Resolve footnote references [^label] in the current block. */ @@ -3871,9 +3871,9 @@ md_resolve_bracket_footnote(MD_CTX* ctx, MD_MARK* opener, MD_MARK* closer, OFF label_beg, label_end; if(!(ctx->parser.flags & MD_FLAG_FOOTNOTES)) - return false; + return 0; if(opener->ch != _T('[') || opener->end >= ctx->size || CH(opener->end) != _T('^')) - return false; + return 0; /* Expand the opener to eat the '^' */ opener->end++; @@ -3882,14 +3882,14 @@ md_resolve_bracket_footnote(MD_CTX* ctx, MD_MARK* opener, MD_MARK* closer, /* Verify the label satisfies the label rules. */ label_beg = opener->end; if(!md_is_footnote_label(ctx, label_beg, &label_end) || label_end != closer->beg) - return false; + return 0; if(label_beg >= label_end) - return false; /* empty label */ + return 0; /* empty label */ def = md_lookup_footnote_def(ctx, STR(label_beg), label_end - label_beg); if(def == NULL) - return false; + return 0; /* Assign index on first reference. */ if(def->index == 0) @@ -3909,7 +3909,7 @@ md_resolve_bracket_footnote(MD_CTX* ctx, MD_MARK* opener, MD_MARK* closer, *last_link_end = closer->end; *p_opener_index = opener->prev; - return true; + return 1; } /* Try to resolve a bracket pair as a CommonMark link or image. @@ -3924,7 +3924,7 @@ md_resolve_bracket_link(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF* last_img_beg, OFF* last_img_end) { MD_LINK_ATTR attr; - int is_link = false; + int is_link = 0; if(next_opener != NULL && next_opener->beg == closer->end) { if(next_closer->beg > closer->end + 1) { @@ -3971,7 +3971,7 @@ md_resolve_bracket_link(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, /* Cancel the link status. */ if(attr.title_needs_free) free(attr.title); - is_link = false; + is_link = 0; break; } @@ -4457,8 +4457,8 @@ md_analyze_permissive_autolink_segment(MD_CTX* ctx, OFF off, OFF end, OFF* p_end { int n_components = 0; int n_open_brackets = 0; - int seen_word_delim = true; - int seen_component_delim = true; + int seen_word_delim = 1; + int seen_component_delim = 1; OFF component_beg = off; if(word_extra == NULL) @@ -4494,18 +4494,18 @@ md_analyze_permissive_autolink_segment(MD_CTX* ctx, OFF off, OFF end, OFF* p_end } if(ISALNUM(off) || ISANYOF(off, word_extra)) { - seen_word_delim = false; - seen_component_delim = false; + seen_word_delim = 0; + seen_component_delim = 0; } else { if(seen_word_delim) break; if(ISANYOF(off, word_delims)) { - seen_word_delim = true; + seen_word_delim = 1; } else if(component_delim != _T('\0') && CH(off) == component_delim) { if(seen_component_delim) break; - seen_component_delim = true; + seen_component_delim = 1; component_beg = off; n_components++; } else { @@ -4519,7 +4519,7 @@ md_analyze_permissive_autolink_segment(MD_CTX* ctx, OFF off, OFF end, OFF* p_end off++; } - /* Rollback falsely consumed delimiter. */ + /* Rollback 0ly consumed delimiter. */ if(seen_word_delim || seen_component_delim) off = (scan_backwards ? off+1 : off-1); @@ -4550,7 +4550,7 @@ md_analyze_permissive_autolink(MD_CTX* ctx, int mark_index) /* E-mail requires the user name (before '@', i.e. scanning backwards). */ if(opener->ch == '@') { MD_ASSERT(CH(opener->beg) == _T('@')); - if(md_analyze_permissive_autolink_segment(ctx, beg, line_beg, &beg, true, + if(md_analyze_permissive_autolink_segment(ctx, beg, line_beg, &beg, 1, _T('\0'), NULL, _T(".-_+"), &left_cursor) < 1) return; @@ -4575,14 +4575,14 @@ md_analyze_permissive_autolink(MD_CTX* ctx, int mark_index) /* Scan for hostname segment. Hostname is mandatory and requires at least two * components delimited with a dot. */ - if(md_analyze_permissive_autolink_segment(ctx, end, line_end, &end, false, + if(md_analyze_permissive_autolink_segment(ctx, end, line_end, &end, 0, _T('.'), NULL, _T("-_"), &right_cursor) < 2) return; if(opener->ch != '@') { /* Scan for path segment. */ if(end < line_end && CH(end) == _T('/')) { - if(md_analyze_permissive_autolink_segment(ctx, end+1, line_end, &end, false, + if(md_analyze_permissive_autolink_segment(ctx, end+1, line_end, &end, 0, _T('/'), _T(".+-_~%"), NULL, &right_cursor) < 0) return; @@ -4593,14 +4593,14 @@ md_analyze_permissive_autolink(MD_CTX* ctx, int mark_index) /* Scan for query segment. */ if(end < line_end && CH(end) == _T('?')) { - if(md_analyze_permissive_autolink_segment(ctx, end+1, line_end, &end, false, + if(md_analyze_permissive_autolink_segment(ctx, end+1, line_end, &end, 0, _T('&'), _T("._=()"), _T("+-"), &right_cursor) < 0) return; } /* Scan for fragment segment. */ if(end < line_end && CH(end) == _T('#')) { - if(md_analyze_permissive_autolink_segment(ctx, end+1, line_end, &end, false, + if(md_analyze_permissive_autolink_segment(ctx, end+1, line_end, &end, 0, _T('\0'), NULL, _T(".-+_"), &right_cursor) < 0) return; } @@ -5058,7 +5058,7 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) MD_CHECK(md_enter_leave_span_a(ctx, (mark->ch != ']'), (opener->ch == '!' ? MD_SPAN_IMG : MD_SPAN_A), - STR(dest_mark->beg), dest_mark->end - dest_mark->beg, false, + STR(dest_mark->beg), dest_mark->end - dest_mark->beg, 0, md_mark_get_ptr(ctx, (int)(title_mark - ctx->marks)), title_mark->prev)); @@ -5116,7 +5116,7 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) if(closer->flags & MD_MARK_VALIDPERMISSIVEAUTOLINK) MD_CHECK(md_enter_leave_span_a(ctx, (mark->flags & MD_MARK_OPENER), - MD_SPAN_A, dest, dest_size, true, NULL, 0)); + MD_SPAN_A, dest, dest_size, 1, NULL, 0)); break; } @@ -5279,7 +5279,7 @@ md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end, /* Break the line into table cells by identifying pipe characters who * form the cell boundary. */ - MD_CHECK(md_analyze_inlines(ctx, &line, 1, true)); + MD_CHECK(md_analyze_inlines(ctx, &line, 1, 1)); /* We have to remember the cell boundaries in local buffer because * ctx->marks[] shall be reused during cell contents processing. */ @@ -5412,7 +5412,7 @@ md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_li int i; int ret; - MD_CHECK(md_analyze_inlines(ctx, lines, n_lines, false)); + MD_CHECK(md_analyze_inlines(ctx, lines, n_lines, 0)); MD_CHECK(md_process_inlines(ctx, lines, n_lines)); abort: @@ -5532,7 +5532,7 @@ md_process_leaf_block(MD_CTX* ctx, MD_BLOCK* block) MD_ATTRIBUTE_BUILD info_build = { 0 }; MD_ATTRIBUTE_BUILD lang_build = { 0 }; int is_in_tight_list; - int clean_fence_code_detail = false; + int clean_fence_code_detail = 0; int ret = 0; /* For large tables check the table density: If it's too low, lets suppress @@ -5563,7 +5563,7 @@ md_process_leaf_block(MD_CTX* ctx, MD_BLOCK* block) memset(&det, 0, sizeof(det)); if(ctx->n_containers == 0) - is_in_tight_list = false; + is_in_tight_list = 0; else is_in_tight_list = !ctx->containers[ctx->n_containers-1].is_loose; @@ -5576,7 +5576,7 @@ md_process_leaf_block(MD_CTX* ctx, MD_BLOCK* block) /* For fenced code block, we may need to set the info string. */ if(block->data != 0) { memset(&det.code, 0, sizeof(MD_BLOCK_CODE_DETAIL)); - clean_fence_code_detail = true; + clean_fence_code_detail = 1; MD_CHECK(md_setup_fenced_code_detail(ctx, block, &det.code, &info_build, &lang_build)); } break; @@ -5665,13 +5665,13 @@ md_process_all_blocks(MD_CTX* ctx) switch(block->type) { case MD_BLOCK_UL: - det.ul.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? false : true; + det.ul.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? 0 : 1; det.ul.mark = (CHAR) block->data; break; case MD_BLOCK_OL: det.ol.start = block->n_lines; - det.ol.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? false : true; + det.ol.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? 0 : 1; det.ol.mark_delimiter = (CHAR) block->data; break; @@ -5709,13 +5709,13 @@ md_process_all_blocks(MD_CTX* ctx) MD_ENTER_BLOCK(block->type, &det); if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL) { - ctx->containers[ctx->n_containers].is_loose = (block->flags & MD_BLOCK_LOOSE_LIST) ? true : false; + ctx->containers[ctx->n_containers].is_loose = (block->flags & MD_BLOCK_LOOSE_LIST) ? 1 : 0; ctx->n_containers++; } else if(block->type == MD_BLOCK_QUOTE || block->type == MD_BLOCK_ADMONITION) { /* This causes that any text in a block quote, even if * nested inside a tight list item, is wrapped with *

    ...

    . */ - ctx->containers[ctx->n_containers].is_loose = true; + ctx->containers[ctx->n_containers].is_loose = 1; ctx->n_containers++; } } @@ -5876,7 +5876,7 @@ md_consume_link_reference_definitions(MD_CTX* ctx) /* We may need to turn the first line after the link ref. def(s) into HR. * (https://github.com/mity/md4c/issues/414) */ if(n < n_lines && md_is_hr_line(ctx, lines[n].beg, &ignored, &ignored)) { - inject_hr = true; + inject_hr = 1; n++; /* Remove one more line below. */ } @@ -6045,7 +6045,7 @@ md_is_hr_line(MD_CTX* ctx, OFF beg, OFF* p_end, OFF* p_killer) int n = 1; if(!ISANYOF(beg, _T("-_*"))) - return false; + return 0; while(off < ctx->size && (CH(off) == CH(beg) || CH(off) == _T(' ') || CH(off) == _T('\t'))) { if(CH(off) == CH(beg)) @@ -6055,17 +6055,17 @@ md_is_hr_line(MD_CTX* ctx, OFF beg, OFF* p_end, OFF* p_killer) if(n < 3) { *p_killer = off; - return false; + return 0; } /* Nothing else can be present on the line. */ if(off < ctx->size && !ISNEWLINE(off)) { *p_killer = off; - return false; + return 0; } *p_end = off; - return true; + return 1; } static int @@ -6079,18 +6079,18 @@ md_is_atxheader_line(MD_CTX* ctx, OFF beg, OFF* p_beg, OFF* p_end, unsigned* p_l n = off - beg; if(n > 6) - return false; + return 0; *p_level = n; if(!(ctx->parser.flags & MD_FLAG_PERMISSIVEATXHEADERS) && off < ctx->size && !ISBLANK(off) && !ISNEWLINE(off)) - return false; + return 0; while(off < ctx->size && ISBLANK(off)) off++; *p_beg = off; *p_end = off; - return true; + return 1; } static int @@ -6107,35 +6107,35 @@ md_is_setext_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_level) /* But nothing more is allowed on the line. */ if(off < ctx->size && !ISNEWLINE(off)) - return false; + return 0; *p_level = (CH(beg) == _T('=') ? 1 : 2); *p_end = off; - return true; + return 1; } static int md_is_table_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_col_count) { OFF off = beg; - int found_pipe = false; + int found_pipe = 0; unsigned col_count = 0; if(off < ctx->size && CH(off) == _T('|')) { - found_pipe = true; + found_pipe = 1; off++; while(off < ctx->size && ISWHITESPACE(off)) off++; } while(1) { - int delimited = false; + int delimited = 0; /* Cell underline ("-----", ":----", "----:" or ":----:") */ if(off < ctx->size && CH(off) == _T(':')) off++; if(off >= ctx->size || CH(off) != _T('-')) - return false; + return 0; while(off < ctx->size && CH(off) == _T('-')) off++; if(off < ctx->size && CH(off) == _T(':')) @@ -6147,8 +6147,8 @@ md_is_table_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_col_count) while(off < ctx->size && ISWHITESPACE(off)) off++; if(off < ctx->size && CH(off) == _T('|')) { - delimited = true; - found_pipe = true; + delimited = 1; + found_pipe = 1; off++; while(off < ctx->size && ISWHITESPACE(off)) off++; @@ -6159,15 +6159,15 @@ md_is_table_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_col_count) break; if(!delimited) - return false; + return 0; } if(!found_pipe) - return false; + return 0; *p_end = off; *p_col_count = col_count; - return true; + return 1; } static int @@ -6180,7 +6180,7 @@ md_is_opening_code_fence(MD_CTX* ctx, OFF beg, OFF* p_end) /* Fence must have at least three characters. */ if(off - beg < 3) - return false; + return 0; ctx->code_fence_length = off - beg; @@ -6192,19 +6192,19 @@ md_is_opening_code_fence(MD_CTX* ctx, OFF beg, OFF* p_end) while(off < ctx->size && !ISNEWLINE(off)) { /* Backtick-based fence must not contain '`' in the info string. */ if(CH(beg) == _T('`') && CH(off) == _T('`')) - return false; + return 0; off++; } *p_end = off; - return true; + return 1; } static int md_is_closing_code_fence(MD_CTX* ctx, CHAR ch, OFF beg, OFF* p_end) { OFF off = beg; - int ret = false; + int ret = 0; /* Closing fence must have at least the same length and use same char as * opening one. */ @@ -6221,7 +6221,7 @@ md_is_closing_code_fence(MD_CTX* ctx, CHAR ch, OFF beg, OFF* p_end) if(off < ctx->size && !ISNEWLINE(off)) goto out; - ret = true; + ret = 1; out: /* Note we set *p_end even on failure: If we are not closing fence, caller @@ -6272,7 +6272,7 @@ static const TAG xx[] = { Xend }; #undef X #undef Xend -/* Returns type of the raw HTML block, or false if it is not HTML block. +/* Returns type of the raw HTML block, or 0 if it is not HTML block. * (Refer to CommonMark specification for details about the types.) */ static int @@ -6356,7 +6356,7 @@ md_is_html_block_start_condition(MD_CTX* ctx, OFF beg) } } - return false; + return 0; } /* Case sensitive check whether there is a substring 'what' between 'beg' @@ -6370,15 +6370,15 @@ md_line_contains(MD_CTX* ctx, OFF beg, const CHAR* what, SZ what_len, OFF* p_end break; if(memcmp(STR(i), what, what_len * sizeof(CHAR)) == 0) { *p_end = i + what_len; - return true; + return 1; } } *p_end = i; - return false; + return 0; } -/* Returns type of HTML block end condition or false if not an end condition. +/* Returns type of HTML block end condition or 0 if not an end condition. * * Note it fills p_end even when it is not end condition as the caller * does not need to analyze contents of a raw HTML block. @@ -6400,7 +6400,7 @@ md_is_html_block_end_condition(MD_CTX* ctx, OFF beg, OFF* p_end) CH(off+2+t1[i].len) == _T('>')) { *p_end = off+2+t1[i].len+1; - return true; + return 1; } } } @@ -6408,20 +6408,20 @@ md_is_html_block_end_condition(MD_CTX* ctx, OFF beg, OFF* p_end) off++; } *p_end = off; - return false; + return 0; } case 2: - return (md_line_contains(ctx, beg, _T("-->"), 3, p_end) ? 2 : false); + return (md_line_contains(ctx, beg, _T("-->"), 3, p_end) ? 2 : 0); case 3: - return (md_line_contains(ctx, beg, _T("?>"), 2, p_end) ? 3 : false); + return (md_line_contains(ctx, beg, _T("?>"), 2, p_end) ? 3 : 0); case 4: - return (md_line_contains(ctx, beg, _T(">"), 1, p_end) ? 4 : false); + return (md_line_contains(ctx, beg, _T(">"), 1, p_end) ? 4 : 0); case 5: - return (md_line_contains(ctx, beg, _T("]]>"), 3, p_end) ? 5 : false); + return (md_line_contains(ctx, beg, _T("]]>"), 3, p_end) ? 5 : 0); case 6: MD_FALLTHROUGH(); case 7: @@ -6430,12 +6430,12 @@ md_is_html_block_end_condition(MD_CTX* ctx, OFF beg, OFF* p_end) *p_end = beg; return ctx->html_block_type; } - return false; + return 0; default: MD_UNREACHABLE(); } - return false; + return 0; } @@ -6444,14 +6444,14 @@ md_is_container_compatible(const MD_CONTAINER* pivot, const MD_CONTAINER* contai { /* Block quote has no "items" like lists. */ if(container->ch == _T('>')) - return false; + return 0; if(container->ch != pivot->ch) - return false; + return 0; if(container->mark_indent > pivot->contents_indent) - return false; + return 0; - return true; + return 1; } static int @@ -6484,12 +6484,12 @@ md_enter_child_containers(MD_CTX* ctx, int n_children) for(i = ctx->n_containers - n_children; i < ctx->n_containers; i++) { MD_CONTAINER* c = &ctx->containers[i]; - int is_ordered_list = false; + int is_ordered_list = 0; switch(c->ch) { case _T(')'): case _T('.'): - is_ordered_list = true; + is_ordered_list = 1; MD_FALLTHROUGH(); case _T('-'): @@ -6532,12 +6532,12 @@ md_leave_child_containers(MD_CTX* ctx, int n_keep) while(ctx->n_containers > n_keep) { MD_CONTAINER* c = &ctx->containers[ctx->n_containers-1]; - int is_ordered_list = false; + int is_ordered_list = 0; switch(c->ch) { case _T(')'): case _T('.'): - is_ordered_list = true; + is_ordered_list = 1; MD_FALLTHROUGH(); case _T('-'): @@ -6576,29 +6576,29 @@ md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTA OFF max_end; if(off >= ctx->size || indent >= ctx->code_indent_offset) - return false; + return 0; /* Check for block quote mark. */ if(CH(off) == _T('>')) { off++; p_container->ch = _T('>'); - p_container->is_loose = false; - p_container->is_task = false; + p_container->is_loose = 0; + p_container->is_task = 0; p_container->mark_indent = indent; p_container->contents_indent = indent + 1; *p_end = off; - return true; + return 1; } /* Check for list item bullet mark. */ if(ISANYOF(off, _T("-+*")) && (off+1 >= ctx->size || ISBLANK(off+1) || ISNEWLINE(off+1))) { p_container->ch = CH(off); - p_container->is_loose = false; - p_container->is_task = false; + p_container->is_loose = 0; + p_container->is_task = 0; p_container->mark_indent = indent; p_container->contents_indent = indent + 1; *p_end = off+1; - return true; + return 1; } /* Check for ordered list item marks. */ @@ -6616,15 +6616,15 @@ md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTA (off+1 >= ctx->size || ISBLANK(off+1) || ISNEWLINE(off+1))) { p_container->ch = CH(off); - p_container->is_loose = false; - p_container->is_task = false; + p_container->is_loose = 0; + p_container->is_task = 0; p_container->mark_indent = indent; p_container->contents_indent = indent + off - beg + 1; *p_end = off+1; - return true; + return 1; } - return false; + return 0; } static unsigned @@ -6666,7 +6666,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, line->indent = md_line_indentation(ctx, total_indent, off, &off); total_indent += line->indent; line->beg = off; - line->enforce_new_block = false; + line->enforce_new_block = 0; /* Given the indentation and block quote marks '>', determine how many of * the current containers are our parents. */ @@ -6707,7 +6707,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, } } - while(true) { + while(1) { /* Check whether we are fenced code continuation. */ if(pivot_line->type == MD_LINE_FENCEDCODE) { line->beg = off; @@ -6717,7 +6717,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, if(line->indent < ctx->code_indent_offset) { if(md_is_closing_code_fence(ctx, CH(pivot_line->beg), off, &off)) { line->type = MD_LINE_BLANK; - ctx->last_line_has_list_loosening_effect = false; + ctx->last_line_has_list_loosening_effect = 0; break; } } @@ -6772,7 +6772,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, line->indent -= ctx->code_indent_offset; else line->indent = 0; - ctx->last_line_has_list_loosening_effect = false; + ctx->last_line_has_list_loosening_effect = 0; } else { line->type = MD_LINE_BLANK; ctx->consecutive_blank_lines++; @@ -6803,7 +6803,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, } ctx->consecutive_blank_lines = 0; - ctx->last_line_has_list_loosening_effect = false; + ctx->last_line_has_list_loosening_effect = 0; } /* Check whether we are Setext underline. */ @@ -6944,7 +6944,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, if(md_is_opening_code_fence(ctx, off, &off)) { line->type = MD_LINE_FENCEDCODE; line->data = 1; - line->enforce_new_block = true; + line->enforce_new_block = 1; break; } } @@ -6966,7 +6966,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, ctx->html_block_type = 0; } - line->enforce_new_block = true; + line->enforce_new_block = 1; line->type = MD_LINE_HTML; break; } @@ -7008,7 +7008,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, (tmp + 3 == ctx->size || ISBLANK(tmp+3) || ISNEWLINE(tmp+3))) { MD_CONTAINER* task_container = (n_children > 0 ? &ctx->containers[ctx->n_containers-1] : &container); - task_container->is_task = true; + task_container->is_task = 1; task_container->task_mark_off = tmp + 1; off = tmp + 3; while(off < ctx->size && ISWHITESPACE(off)) @@ -7097,7 +7097,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, if(line->end - line->beg == md_strlen(MD_ADMONITION_TAGS[i]) + 3 && md_ascii_case_eq(STR(line->beg+2), MD_ADMONITION_TAGS[i], line->end - line->beg - 3)) { - ctx->containers[ctx->n_containers-1].is_admonition = true; + ctx->containers[ctx->n_containers-1].is_admonition = 1; ctx->containers[ctx->n_containers-1].admonition_type = i; line->type = MD_LINE_BLANK; break; From 0f60df489dd176f891776bda7ca14b17507418fe Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 05:26:02 +0900 Subject: [PATCH 092/168] huh --- external/md4c.c | 1 - 1 file changed, 1 deletion(-) diff --git a/external/md4c.c b/external/md4c.c index 8665a14..1c23cd1 100644 --- a/external/md4c.c +++ b/external/md4c.c @@ -24,7 +24,6 @@ */ #include -#include #include #include #include From 01356a07666b56d4462138bd73606e514d602d05 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 05:29:31 +0900 Subject: [PATCH 093/168] i love msvc --- external/md4c.c | 72 +++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/external/md4c.c b/external/md4c.c index 1c23cd1..c582ef9 100644 --- a/external/md4c.c +++ b/external/md4c.c @@ -157,7 +157,7 @@ struct MD_LABEL_HASH_TABLE_tag { }; -/* During analyzes of inline marks, we need to manage stacks of unresolved +/* During analyzes of __inline marks, we need to manage stacks of unresolved * openers of the given type. * The stack connects the marks via MD_MARK::next; */ @@ -190,7 +190,7 @@ struct MD_CTX_tag { MD_LABEL_HASH_TABLE footnote_hashtable; unsigned next_footnote_index; /* 1-based counter for sequential numbering */ - /* Stack of inline/span markers. + /* Stack of __inline/span markers. * This is only used for parsing a single block contents but by storing it * here we may reuse the stack for subsequent blocks; i.e. we have fewer * (re)allocations. */ @@ -204,7 +204,7 @@ struct MD_CTX_tag { char mark_char_map[256]; #endif - /* For resolving of inline spans. */ + /* For resolving of __inline spans. */ MD_MARKSTACK opener_stacks[20]; #define ASTERISK_OPENERS_oo_mod3_0 (ctx->opener_stacks[0]) /* Opener-only */ #define ASTERISK_OPENERS_oo_mod3_1 (ctx->opener_stacks[1]) @@ -228,7 +228,7 @@ struct MD_CTX_tag { #define PLUS_OPENERS (ctx->opener_stacks[19]) /* Stack of dummies which need to call free() for pointers stored in them. - * These are constructed during inline parsing and freed after all the block + * These are constructed during __inline parsing and freed after all the block * is processed (i.e. all callbacks referring those strings are called). */ MD_MARKSTACK ptr_stack; @@ -370,7 +370,7 @@ struct MD_VERBATIMLINE_tag { /* Case insensitive check of string equality. */ -static inline int +static __inline int md_ascii_case_eq(const CHAR* s1, const CHAR* s2, SZ n) { OFF i; @@ -388,7 +388,7 @@ md_ascii_case_eq(const CHAR* s1, const CHAR* s2, SZ n) return 1; } -static inline int +static __inline int md_ascii_eq(const CHAR* s1, const CHAR* s2, SZ n) { return memcmp(s1, s2, n * sizeof(CHAR)) == 0; @@ -887,7 +887,7 @@ struct MD_UNICODE_FOLD_INFO_tag { #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf16le__(STR(off), ctx->size - (off), NULL)) #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf16le_before__(ctx, off)) - static inline int + static __inline int md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size) { return md_decode_utf16le__(str+off, str_size-off, p_char_size); @@ -968,7 +968,7 @@ struct MD_UNICODE_FOLD_INFO_tag { #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf8__(STR(off), ctx->size - (off), NULL)) #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf8_before__(ctx, off)) - static inline unsigned + static __inline unsigned md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size) { return md_decode_utf8__(str+off, str_size-off, p_char_size); @@ -981,7 +981,7 @@ struct MD_UNICODE_FOLD_INFO_tag { #define ISUNICODEPUNCT(off) ISPUNCT(off) #define ISUNICODEPUNCTBEFORE(off) ISPUNCT((off)-1) - static inline void + static __inline void md_get_unicode_fold_info(unsigned codepoint, MD_UNICODE_FOLD_INFO* info) { info->codepoints[0] = codepoint; @@ -990,7 +990,7 @@ struct MD_UNICODE_FOLD_INFO_tag { info->n_codepoints = 1; } - static inline unsigned + static __inline unsigned md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_size) { MD_UNUSED(str_size); @@ -1088,7 +1088,7 @@ md_skip_unicode_whitespace(const CHAR* label, OFF off, SZ size) *** Recognizing raw HTML *** ******************************/ -/* md_is_html_tag() may be called when processing inlines (inline raw HTML) +/* md_is_html_tag() may be called when processing __inlines (__inline raw HTML) * or when breaking document to blocks (checking for start of HTML block type 7). * * When breaking document to blocks, we do not yet know line boundaries, but @@ -1420,7 +1420,7 @@ md_is_entity_str(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end } } -static inline int +static __inline int md_is_entity(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end) { return md_is_entity_str(ctx, ctx->text, beg, max_end, p_end); @@ -1597,7 +1597,7 @@ abort: #define MD_FNV1A_BASE 2166136261U #define MD_FNV1A_PRIME 16777619U -static inline unsigned +static __inline unsigned md_fnv1a(unsigned base, const void* data, size_t n) { const unsigned char* buf = (const unsigned char*) data; @@ -2169,7 +2169,7 @@ md_free_footnote_defs(MD_CTX* ctx) *** Recognizing Links *** ***************************/ -/* Note this code is partially shared between processing inlines and blocks +/* Note this code is partially shared between processing __inlines and blocks * as reference definitions and links share some helper parser functions. */ @@ -2333,7 +2333,7 @@ md_is_link_destination_B(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, return 1; } -static inline int +static __inline int md_is_link_destination(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, OFF* p_contents_beg, OFF* p_contents_end) { @@ -2586,7 +2586,7 @@ abort: } static int -md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, +md_is___inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, OFF beg, OFF* p_end, MD_LINK_ATTR* attr) { MD_SIZE line_index = 0; @@ -2705,7 +2705,7 @@ md_free_ref_defs(MD_CTX* ctx) *** Processing Inlines (a.k.a Spans) *** ******************************************/ -/* We process inlines in few phases: +/* We process __inlines in few phases: * * (1) We go through the block text and collect all significant characters * which may start/end a span or some other significant position into @@ -2850,6 +2850,8 @@ md_opener_stack(MD_CTX* ctx, int mark_index) default: MD_UNREACHABLE(); } + + return NULL; } static MD_MARK* @@ -2894,14 +2896,14 @@ md_add_mark(MD_CTX* ctx) } while(0) -static inline void +static __inline void md_mark_stack_push(MD_CTX* ctx, MD_MARKSTACK* stack, int mark_index) { ctx->marks[mark_index].next = stack->top; stack->top = mark_index; } -static inline int +static __inline int md_mark_stack_pop(MD_CTX* ctx, MD_MARKSTACK* stack) { int top = stack->top; @@ -2912,21 +2914,21 @@ md_mark_stack_pop(MD_CTX* ctx, MD_MARKSTACK* stack) /* Sometimes, we need to store a pointer into the mark. It can only happen * for dummy marks. */ -static inline void +static __inline void md_mark_store_ptr(MD_CTX* ctx, int mark_index, void* ptr) { MD_ASSERT(ctx->marks[mark_index].ch == 'D'); ctx->marks[mark_index].pointer = ptr; } -static inline void* +static __inline void* md_mark_get_ptr(MD_CTX* ctx, int mark_index) { MD_ASSERT(ctx->marks[mark_index].ch == 'D'); return ctx->marks[mark_index].pointer; } -static inline void +static __inline void md_resolve_range(MD_CTX* ctx, int opener_index, int closer_index) { MD_MARK* opener = &ctx->marks[opener_index]; @@ -3716,7 +3718,7 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int table_m } /* Add a dummy mark at the end of the mark vector to simplify - * process_inlines(). */ + * process___inlines(). */ ADD_MARK(127, ctx->size, ctx->size, MD_MARK_RESOLVED); abort: @@ -3949,11 +3951,11 @@ md_resolve_bracket_link(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, } } else { if(closer->end < ctx->size && CH(closer->end) == _T('(')) { - /* Might be inline link. */ - OFF inline_link_end = UINT_MAX; + /* Might be __inline link. */ + OFF __inline_link_end = UINT_MAX; int following_mark_index = closer_index + 1; - is_link = md_is_inline_link_spec(ctx, lines, n_lines, closer->end, &inline_link_end, &attr); + is_link = md_is___inline_link_spec(ctx, lines, n_lines, closer->end, &__inline_link_end, &attr); if(is_link < 0) return -1; @@ -3963,10 +3965,10 @@ md_resolve_bracket_link(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, while(following_mark_index < ctx->n_marks) { MD_MARK* mark = &ctx->marks[following_mark_index]; - if(mark->beg >= inline_link_end) + if(mark->beg >= __inline_link_end) break; if((mark->flags & (MD_MARK_OPENER | MD_MARK_RESOLVED)) == (MD_MARK_OPENER | MD_MARK_RESOLVED)) { - if(ctx->marks[mark->next].beg >= inline_link_end) { + if(ctx->marks[mark->next].beg >= __inline_link_end) { /* Cancel the link status. */ if(attr.title_needs_free) free(attr.title); @@ -3983,7 +3985,7 @@ md_resolve_bracket_link(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, if(is_link) { /* Eat the "(...)" */ - closer->end = inline_link_end; + closer->end = __inline_link_end; md_disable_marks(ctx, closer_index+1, following_mark_index); } } @@ -4626,7 +4628,7 @@ md_analyze_permissive_autolink(MD_CTX* ctx, int mark_index) #define MD_ANALYZE_NOSKIP_EMPH 0x01 -static inline void +static __inline void md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int mark_beg, int mark_end, const CHAR* mark_chars, const CHAR* noskip_mark_chars) { @@ -4696,7 +4698,7 @@ md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, /* Analyze marks (build ctx->marks). */ static int -md_analyze_inlines(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int table_mode) +md_analyze___inlines(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int table_mode) { int i; int ret; @@ -4853,7 +4855,7 @@ abort: /* Render the output, accordingly to the analyzed ctx->marks. */ static int -md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) +md_process___inlines(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines) { MD_TEXTTYPE text_type; const MD_LINE* line = lines; @@ -5278,7 +5280,7 @@ md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end, /* Break the line into table cells by identifying pipe characters who * form the cell boundary. */ - MD_CHECK(md_analyze_inlines(ctx, &line, 1, 1)); + MD_CHECK(md_analyze___inlines(ctx, &line, 1, 1)); /* We have to remember the cell boundaries in local buffer because * ctx->marks[] shall be reused during cell contents processing. */ @@ -5411,8 +5413,8 @@ md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_li int i; int ret; - MD_CHECK(md_analyze_inlines(ctx, lines, n_lines, 0)); - MD_CHECK(md_process_inlines(ctx, lines, n_lines)); + MD_CHECK(md_analyze___inlines(ctx, lines, n_lines, 0)); + MD_CHECK(md_process___inlines(ctx, lines, n_lines)); abort: /* Free any temporary memory blocks stored within some dummy marks. */ From 09f2d6c565a8458468162408a811a21b9a439fc0 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 05:53:56 +0900 Subject: [PATCH 094/168] testing ci --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6c1637e..0a8b712 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -26,7 +26,7 @@ pipeline { parallel { stage("Build for Linux 64-bit") { agent { - label "built-in" + label "untrusted" } steps { sh("git clean -dfx") From 0747cf2ec3d9ae68d74a9d1f7dae6b61064a9018 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 05:54:19 +0900 Subject: [PATCH 095/168] testing ci --- Jenkinsfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 0a8b712..4f0b202 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -38,7 +38,7 @@ pipeline { } stage("Build for Windows 32-bit") { agent { - label "built-in" + label "untrusted" } steps { sh("git clean -dfx") @@ -51,7 +51,7 @@ pipeline { } stage("Build for Windows 64-bit") { agent { - label "built-in" + label "untrusted" } steps { sh("git clean -dfx") @@ -76,7 +76,7 @@ pipeline { } stage("Build for Windows 32-bit (Watcom)") { agent { - label "built-in" + label "untrusted" } environment { WATCOM = "/usr/watcom" From 2f224ac912b957cd6baf0fd6ac3c5133c2716b00 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 06:06:07 +0900 Subject: [PATCH 096/168] fixing ci --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 4f0b202..76e3093 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -29,6 +29,7 @@ pipeline { label "untrusted" } steps { + sh("apt-get install build-essential libx11-dev wayland-protocols libwayland-dev") sh("git clean -dfx") sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper") sh("make -j4") From ffae70cbe78e2f7905f0a2a8148914f3a5e2d7b8 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 06:08:45 +0900 Subject: [PATCH 097/168] fixing ci --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 76e3093..4281763 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -29,6 +29,7 @@ pipeline { label "untrusted" } steps { + sh("apt-get update") sh("apt-get install build-essential libx11-dev wayland-protocols libwayland-dev") sh("git clean -dfx") sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper") From 289338a23c5ced89a4c746b62e2e655d269d60db Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 06:13:07 +0900 Subject: [PATCH 098/168] fixing ci --- Jenkinsfile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4281763..8f0033d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,7 +30,7 @@ pipeline { } steps { sh("apt-get update") - sh("apt-get install build-essential libx11-dev wayland-protocols libwayland-dev") + sh("apt-get install -y build-essential libx11-dev wayland-protocols libwayland-dev") sh("git clean -dfx") sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper") sh("make -j4") @@ -43,6 +43,8 @@ pipeline { label "untrusted" } steps { + sh("apt-get update") + sh("apt-get install -y build-essential mingw-w64-i686-dev") sh("git clean -dfx") sh("./configure --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=i686-w64-mingw32") sh("make -j4") @@ -57,6 +59,7 @@ pipeline { } steps { sh("git clean -dfx") + sh("apt-get install -y build-essential mingw-w64-x86-64-dev") sh("./configure --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=x86_64-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw64.dll") @@ -86,6 +89,11 @@ pipeline { PATH = "/usr/watcom/binl64:${env.PATH}" } steps { + sh("git clean -dfx") + sh("apt-get install -y wget") + sh("wget https://github.com/open-watcom/open-watcom-v2/releases/download/Current-build/ow-snapshot.tar.xz") + sh("mkdir -p /usr/watcom") + sh("tar xvf ow-snapshot.tar.xz -C /usr/watcom") sh("git clean -dfx") sh("wmake -f WatMakefile") sh("mv src/Mw.dll MwWat32.dll") From ac7373ebfc15ac891e24f13a4e103b829ab42bd5 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 06:19:49 +0900 Subject: [PATCH 099/168] fix --- Jenkinsfile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 8f0033d..40cd979 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -44,9 +44,9 @@ pipeline { } steps { sh("apt-get update") - sh("apt-get install -y build-essential mingw-w64-i686-dev") + sh("apt-get install -y make mingw-w64") sh("git clean -dfx") - sh("./configure --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=i686-w64-mingw32") + sh("./configure --enable-opengl --cross --target=Windows --host=i686-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw32.dll") sh("mv src/libMw.dll.a libMw32.dll.a") @@ -58,9 +58,10 @@ pipeline { label "untrusted" } steps { + sh("apt-get update") + sh("apt-get install -y make mingw-w64") sh("git clean -dfx") - sh("apt-get install -y build-essential mingw-w64-x86-64-dev") - sh("./configure --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=x86_64-w64-mingw32") + sh("./configure --enable-opengl --cross --target=Windows --host=x86_64-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw64.dll") sh("mv src/libMw.dll.a libMw64.dll.a") @@ -89,8 +90,9 @@ pipeline { PATH = "/usr/watcom/binl64:${env.PATH}" } steps { - sh("git clean -dfx") + sh("apt-get update") sh("apt-get install -y wget") + sh("git clean -dfx") sh("wget https://github.com/open-watcom/open-watcom-v2/releases/download/Current-build/ow-snapshot.tar.xz") sh("mkdir -p /usr/watcom") sh("tar xvf ow-snapshot.tar.xz -C /usr/watcom") From 61cf15f562e5d0f8f470180514fb095b8ee3a6fb Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 06:52:34 +0900 Subject: [PATCH 100/168] ahh --- Dockerfile | 15 +++++++++++++++ Jenkinsfile | 17 ----------------- 2 files changed, 15 insertions(+), 17 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..02a430a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM jenkins/inbound-agent:latest + +USER root + +RUN apt-get update && apt-get install -y build-essential cmake pkg-config mingw-w64 xz-utils wget \ + libx11-dev libxrender-dev libfreetype-dev libwayland-dev wayland-protocols libxkbcommon-dev libcairo-dev libdbus-1-dev libgl-dev libvulkan-dev + +RUN mkdir -p /usr/watcom && wget -q -O /tmp/ow-snapshot.tar.xz https://github.com/open-watcom/open-watcom-v2/releases/download/Current-build/ow-snapshot.tar.xz +RUN tar xJf /tmp/ow-snapshot.tar.xz -C /usr/watcom && rm -f /tmp/ow-snapshot.tar.xz + +ENV PATH=/usr/watcom/binl64:$PATH +ENV WATCOM=/usr/watcom +ENV INCLUDE=/usr/watcom/h + +USER jenkins diff --git a/Jenkinsfile b/Jenkinsfile index 40cd979..4e17a07 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -29,8 +29,6 @@ pipeline { label "untrusted" } steps { - sh("apt-get update") - sh("apt-get install -y build-essential libx11-dev wayland-protocols libwayland-dev") sh("git clean -dfx") sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper") sh("make -j4") @@ -43,8 +41,6 @@ pipeline { label "untrusted" } steps { - sh("apt-get update") - sh("apt-get install -y make mingw-w64") sh("git clean -dfx") sh("./configure --enable-opengl --cross --target=Windows --host=i686-w64-mingw32") sh("make -j4") @@ -58,8 +54,6 @@ pipeline { label "untrusted" } steps { - sh("apt-get update") - sh("apt-get install -y make mingw-w64") sh("git clean -dfx") sh("./configure --enable-opengl --cross --target=Windows --host=x86_64-w64-mingw32") sh("make -j4") @@ -84,18 +78,7 @@ pipeline { agent { label "untrusted" } - environment { - WATCOM = "/usr/watcom" - INCLUDE = "/usr/watcom/h:/usr/watcom/h/nt" - PATH = "/usr/watcom/binl64:${env.PATH}" - } steps { - sh("apt-get update") - sh("apt-get install -y wget") - sh("git clean -dfx") - sh("wget https://github.com/open-watcom/open-watcom-v2/releases/download/Current-build/ow-snapshot.tar.xz") - sh("mkdir -p /usr/watcom") - sh("tar xvf ow-snapshot.tar.xz -C /usr/watcom") sh("git clean -dfx") sh("wmake -f WatMakefile") sh("mv src/Mw.dll MwWat32.dll") From 1f8b4074a9a167df9cea3903b118dc8003e2770a Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 06:58:36 +0900 Subject: [PATCH 101/168] ok --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 02a430a..10c8ea7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,12 +4,13 @@ USER root RUN apt-get update && apt-get install -y build-essential cmake pkg-config mingw-w64 xz-utils wget \ libx11-dev libxrender-dev libfreetype-dev libwayland-dev wayland-protocols libxkbcommon-dev libcairo-dev libdbus-1-dev libgl-dev libvulkan-dev +RUN apt-get install -y libglu-dev libegl-dev RUN mkdir -p /usr/watcom && wget -q -O /tmp/ow-snapshot.tar.xz https://github.com/open-watcom/open-watcom-v2/releases/download/Current-build/ow-snapshot.tar.xz RUN tar xJf /tmp/ow-snapshot.tar.xz -C /usr/watcom && rm -f /tmp/ow-snapshot.tar.xz ENV PATH=/usr/watcom/binl64:$PATH ENV WATCOM=/usr/watcom -ENV INCLUDE=/usr/watcom/h +ENV INCLUDE=/usr/watcom/h:/usr/watcom/h/nt USER jenkins From cb0d7b8583eafd77166219564f500793910bc170 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 14 Sep 2026 15:09:14 -0700 Subject: [PATCH 102/168] wayland drag and drop --- NTMakefile | 12 +++- WatMakefile | 12 +++- examples/basic/dnd.c | 59 ++++++++++++++++ include/Mw/LowLevel/Wayland.h | 3 + pl/rules.pl | 1 + src/backend/wayland/interfaces.c | 115 +++++++++++++++++++++++++++---- 6 files changed, 186 insertions(+), 16 deletions(-) create mode 100644 examples/basic/dnd.c diff --git a/NTMakefile b/NTMakefile index 26723bc..213800d 100644 --- a/NTMakefile +++ b/NTMakefile @@ -6,9 +6,9 @@ MW_LDFLAGS = /DLL EXE_CFLAGS = /Iinclude EXE_LDFLAGS = .SUFFIXES: .obj .c -all: src\Mw.dll examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\document.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe +all: src\Mw.dll examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\dnd.exe examples\basic\document.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe lib: src\Mw.dll -examples: examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\document.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe +examples: examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\dnd.exe examples\basic\document.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe clean: del /f /q external\libz\src\adler32.obj del /f /q external\libz\src\compress.obj @@ -112,6 +112,7 @@ clean: del /f /q examples\basic\clipboard.obj del /f /q examples\basic\colorpicker.obj del /f /q examples\basic\combobox.obj + del /f /q examples\basic\dnd.obj del /f /q examples\basic\document.obj del /f /q examples\basic\example.obj del /f /q examples\basic\filechooser.obj @@ -140,6 +141,7 @@ clean: del /f /q examples\basic\clipboard.exe del /f /q examples\basic\colorpicker.exe del /f /q examples\basic\combobox.exe + del /f /q examples\basic\dnd.exe del /f /q examples\basic\document.exe del /f /q examples\basic\example.exe del /f /q examples\basic\filechooser.exe @@ -199,6 +201,12 @@ examples\basic\combobox.exe: examples\basic\combobox.obj src\Mw.dll examples\basic\combobox.obj: examples/basic/combobox.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/combobox.c +examples\basic\dnd.exe: examples\basic\dnd.obj src\Mw.dll + $(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\dnd.obj src\Mw.lib + +examples\basic\dnd.obj: examples/basic/dnd.c + $(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/dnd.c + examples\basic\document.exe: examples\basic\document.obj src\Mw.dll $(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\document.obj src\Mw.lib diff --git a/WatMakefile b/WatMakefile index 7924e17..0b846d1 100644 --- a/WatMakefile +++ b/WatMakefile @@ -5,9 +5,9 @@ MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -d MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt -all: src/Mw.dll examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe +all: src/Mw.dll examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe lib: src/Mw.dll -examples: examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe +examples: examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe clean: .SYMBOLIC %erase external/libz/src/adler32.obj %erase external/libz/src/compress.obj @@ -111,6 +111,7 @@ clean: .SYMBOLIC %erase examples/basic/clipboard.obj %erase examples/basic/colorpicker.obj %erase examples/basic/combobox.obj + %erase examples/basic/dnd.obj %erase examples/basic/document.obj %erase examples/basic/example.obj %erase examples/basic/filechooser.obj @@ -139,6 +140,7 @@ clean: .SYMBOLIC %erase examples/basic/clipboard.exe %erase examples/basic/colorpicker.exe %erase examples/basic/combobox.exe + %erase examples/basic/dnd.exe %erase examples/basic/document.exe %erase examples/basic/example.exe %erase examples/basic/filechooser.exe @@ -198,6 +200,12 @@ examples/basic/combobox.exe: examples/basic/combobox.obj src/Mw.dll examples/basic/combobox.obj: examples/basic/combobox.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/combobox.c +examples/basic/dnd.exe: examples/basic/dnd.obj src/Mw.dll + $(LD) $(EXE_LDFLAGS) name $@ file examples/basic/dnd.obj library clib3r.lib library src/Mw.lib + +examples/basic/dnd.obj: examples/basic/dnd.c + $(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/dnd.c + examples/basic/document.exe: examples/basic/document.obj src/Mw.dll $(LD) $(EXE_LDFLAGS) name $@ file examples/basic/document.obj library clib3r.lib library src/Mw.lib diff --git a/examples/basic/dnd.c b/examples/basic/dnd.c new file mode 100644 index 0000000..f88a650 --- /dev/null +++ b/examples/basic/dnd.c @@ -0,0 +1,59 @@ +#include + +MwWidget window, instructions, text1, cur_text; + +static void MWAPI resize(MwWidget handle, void* user_data, void* call_data) { + unsigned int w, h; + + (void)user_data; + (void)call_data; + + w = MwGetInteger(handle, MwNwidth); + h = MwGetInteger(handle, MwNheight); + + MwVaApply(instructions, + MwNy, 50, + MwNwidth, w - 50 * 2, + MwNheight, h - 125 - 50 * 3, + NULL); + + MwVaApply(text1, + MwNy, 150, + MwNwidth, w - 25 * 2, + MwNheight, h - 125 - 50 * 3, + NULL); +} +static void MWAPI dnd(MwWidget handle, void* user_data, void* call_data) { + char* filename = call_data; + + (void)handle; + (void)user_data; + + if(filename != NULL) { + MwVaApply(cur_text, MwNtext, filename, NULL); + MwForceRender(cur_text); + } +} + +int main() { + MwLibraryInit(); + + window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 400, 400, + MwNtitle, "dnd", + NULL); + instructions = MwVaCreateWidget(MwLabelClass, "button", window, 50, 50, 300, 125, + MwNtext, "drag a file and its name will show up below.", + NULL); + text1 = MwVaCreateWidget(MwLabelClass, "label", window, 25, 150, 300, 75, + MwNtext, "", + NULL); + + cur_text = text1; + + MwAddUserHandler(window, MwNresizeHandler, resize, NULL); + MwAddUserHandler(window, MwNdragAndDropHandler, dnd, NULL); + + resize(window, NULL, NULL); + + MwLoop(window); +} diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index fd97178..44a3983 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -292,6 +292,9 @@ typedef struct wl_clipboard_device_context { struct zwp_primary_selection_offer_v1* zwp; } offer; + const char* accepted_types[6]; + char selected_mime_type[4096]; + MwLL ll; // struct wl_seat* seat; } wl_clipboard_device_context_t; diff --git a/pl/rules.pl b/pl/rules.pl index ad62d6c..551d391 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -207,6 +207,7 @@ new_example("examples/basic/combobox"); new_example("examples/basic/treeview"); new_example("examples/basic/box"); new_example("examples/basic/clipboard"); +new_example("examples/basic/dnd"); new_example("examples/basic/sevensegment"); new_example("examples/basic/calculator"); new_example("examples/basic/filechooser"); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index cbab2ad..eaabf16 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -100,11 +100,32 @@ static void wl_offer(void* data, struct wl_data_offer* wl_data_offer, const char* mime_type) { wl_clipboard_device_context_t* self = data; - wl_data_offer_accept(wl_data_offer, self->ll->wayland.clipboard_serial, mime_type); + int i; + for(i = 0; i < sizeof(self->accepted_types) / sizeof(self->accepted_types[0]); i++) { + if(strcmp(self->accepted_types[i], mime_type) == 0) { + wl_data_offer_accept(wl_data_offer, self->ll->wayland.clipboard_serial, mime_type); + memset(self->selected_mime_type, 0, 4096); + snprintf(self->selected_mime_type, sizeof(self->selected_mime_type), "%s", mime_type); + break; + } + } }; +static void wl_source_actions(void* data, + struct wl_data_offer* wl_data_offer, + uint32_t source_actions) { + + // printf("%d\n", source_actions); +}; + +static void wl_action(void* data, + struct wl_data_offer* wl_data_offer, + uint32_t dnd_action) {}; + struct wl_data_offer_listener offer_listener = { - .offer = wl_offer, + .offer = wl_offer, + .source_actions = wl_source_actions, + .action = wl_action, }; static void wl_data_device_data_offer(void* data, @@ -125,7 +146,7 @@ static void wl_data_device_enter(void* data, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer* id) { - MwLL self = data; + wl_clipboard_device_context_t* self = data; (void)wl_data_device; (void)surface; (void)x; @@ -134,33 +155,86 @@ static void wl_data_device_enter(void* data, WAYLAND_EVENT_OP_START(self); - self->wayland.clipboard_serial = serial; + self->ll->wayland.clipboard_serial = serial; WAYLAND_EVENT_OP_END(self); }; static void wl_data_device_leave(void* data, struct wl_data_device* wl_data_device) { - MwLL self = data; + wl_clipboard_device_context_t* self = data; - WAYLAND_EVENT_OP_START(self); - wl_data_device_destroy(wl_data_device); - WAYLAND_EVENT_OP_END(self); + if(self->offer.wl) { + wl_data_offer_destroy(self->offer.wl); + self->offer.wl = NULL; + } }; static void wl_data_device_motion(void* data, struct wl_data_device* wl_data_device, uint32_t time, wl_fixed_t x, wl_fixed_t y) { - (void)data; (void)wl_data_device; (void)time; (void)x; (void)y; + wl_clipboard_device_context_t* self = data; + + if(self->selected_mime_type[0] != '\0' && self->offer.wl) { + wl_data_offer_set_actions(self->offer.wl, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); + } }; static void wl_data_device_drop(void* data, struct wl_data_device* wl_data_device) { - (void)data; - (void)wl_data_device; + wl_clipboard_device_context_t* self = data; + int fds[2]; + fd_set set; + char* buf = NULL; + struct timeval timeout; + int rc = 0; + + if(pipe(fds) != 0) { + + return; + } + + FD_ZERO(&set); + FD_SET(fds[0], &set); + timeout.tv_sec = 0; + timeout.tv_usec = 1000; + + wl_data_offer_receive(self->offer.wl, self->selected_mime_type, fds[1]); + close(fds[1]); + + MwLLWaylandFlush(self->ll); + wl_display_roundtrip(self->ll->wayland.display); + + while(MwTRUE) { + rc = select(fds[0] + 1, &set, NULL, NULL, &timeout); + if(rc <= 0) { + break; + } else { + char b; + ssize_t n = read(fds[0], &b, sizeof(b)); + if(n <= 0) { + break; + } + arrpush(buf, b); + } + } + arrpush(buf, 0); + close(fds[0]); + + setup_clipboard(self->ll, self->ll->wayland.pointer_seat); + + if(strstr(buf, "file://")) { + MwLLDispatch(self->ll, drag_and_drop, buf + sizeof("file://") - 1); + } else { + MwLLDispatch(self->ll, drag_and_drop, buf); + } + + arrfree(buf); + + self->selected_mime_type[0] = '\0'; }; static void wl_data_device_selection(void* data, @@ -256,6 +330,7 @@ static void wl_data_source_listener_target(void* data, (void)data; (void)wl_data_source; (void)mime_type; + printf("test\n"); }; static void wl_data_source_listener_send(void* data, struct wl_data_source* wl_data_source, @@ -297,6 +372,7 @@ static void wl_data_source_listener_cancelled(void* data, wl_data_source_offer(self->wayland.clipboard_source.wl, "TEXT"); wl_data_source_offer(self->wayland.clipboard_source.wl, "STRING"); wl_data_source_offer(self->wayland.clipboard_source.wl, "UTF8_STRING"); + wl_data_source_offer(self->wayland.clipboard_source.wl, "text/uri-list"); wl_data_source_add_listener(self->wayland.clipboard_source.wl, &wl_data_source_listener, self); @@ -348,7 +424,7 @@ struct zwp_primary_selection_source_v1_listener zwp_primary_selection_source_v1_ /* wl_data_device_manager setup function */ static wayland_protocol_t* wl_data_device_manager_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { (void)version; - wayland->clipboard_manager.wl = wl_registry_bind(wayland->registry, name, &wl_data_device_manager_interface, 2); + wayland->clipboard_manager.wl = wl_registry_bind(wayland->registry, name, &wl_data_device_manager_interface, 3); wayland->clipboard_source.wl = wl_data_device_manager_create_data_source(wayland->clipboard_manager.wl); @@ -357,6 +433,7 @@ static wayland_protocol_t* wl_data_device_manager_setup(MwU32 name, struct _MwLL wl_data_source_offer(wayland->clipboard_source.wl, "TEXT"); wl_data_source_offer(wayland->clipboard_source.wl, "STRING"); wl_data_source_offer(wayland->clipboard_source.wl, "UTF8_STRING"); + wl_data_source_offer(wayland->clipboard_source.wl, "text/uri-list"); wl_data_source_add_listener(wayland->clipboard_source.wl, &wl_data_source_listener, wayland); @@ -1040,6 +1117,13 @@ static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat) { device_ctx_zwp->ll = self; zwp_primary_selection_device_v1_add_listener(device_ctx_zwp->device.zwp, &zwp_primary_selection_device_v1_listener, device_ctx_zwp); arrpush(self->wayland.clipboard_devices_zwp, device_ctx_zwp); + + device_ctx_zwp->accepted_types[0] = "text/plain"; + device_ctx_zwp->accepted_types[1] = "text/plain;charset=utf-8"; + device_ctx_zwp->accepted_types[2] = "TEXT"; + device_ctx_zwp->accepted_types[3] = "STRING"; + device_ctx_zwp->accepted_types[4] = "UTF8_STRING"; + device_ctx_zwp->accepted_types[5] = "text/uri-list"; } static void setup_clipboard(MwLL self, struct wl_seat* wl_seat) { wl_clipboard_device_context_t* device_ctx_wl = malloc(sizeof(wl_clipboard_device_context_t)); @@ -1050,6 +1134,13 @@ static void setup_clipboard(MwLL self, struct wl_seat* wl_seat) { wl_data_device_add_listener(device_ctx_wl->device.wl, &wl_data_device_listener, device_ctx_wl); arrpush(self->wayland.clipboard_devices_wl, device_ctx_wl); + + device_ctx_wl->accepted_types[0] = "text/plain"; + device_ctx_wl->accepted_types[1] = "text/plain;charset=utf-8"; + device_ctx_wl->accepted_types[2] = "TEXT"; + device_ctx_wl->accepted_types[3] = "STRING"; + device_ctx_wl->accepted_types[4] = "UTF8_STRING"; + device_ctx_wl->accepted_types[5] = "text/uri-list"; }; static void keyboard_repeat_info(void* data, From 36e647fcef5c854727aadbeb8fcbe7db8db9bd7d Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 07:16:53 +0900 Subject: [PATCH 103/168] ok --- Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 10c8ea7..0cb38a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,9 +2,7 @@ FROM jenkins/inbound-agent:latest USER root -RUN apt-get update && apt-get install -y build-essential cmake pkg-config mingw-w64 xz-utils wget \ - libx11-dev libxrender-dev libfreetype-dev libwayland-dev wayland-protocols libxkbcommon-dev libcairo-dev libdbus-1-dev libgl-dev libvulkan-dev -RUN apt-get install -y libglu-dev libegl-dev +RUN apt-get update && apt-get install -y build-essential cmake pkg-config mingw-w64 xz-utils wget libx11-dev libxrender-dev libfreetype-dev libwayland-dev wayland-protocols libxkbcommon-dev libcairo-dev libdbus-1-dev libgl-dev libvulkan-dev libglu-dev libegl-dev libgbm-dev RUN mkdir -p /usr/watcom && wget -q -O /tmp/ow-snapshot.tar.xz https://github.com/open-watcom/open-watcom-v2/releases/download/Current-build/ow-snapshot.tar.xz RUN tar xJf /tmp/ow-snapshot.tar.xz -C /usr/watcom && rm -f /tmp/ow-snapshot.tar.xz From 2835b917a9e2eb6881be5ce4c41c26123102c73b Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 07:24:41 +0900 Subject: [PATCH 104/168] ok --- Jenkinsfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4e17a07..8e42285 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -26,7 +26,7 @@ pipeline { parallel { stage("Build for Linux 64-bit") { agent { - label "untrusted" + label "built-in" } steps { sh("git clean -dfx") @@ -38,7 +38,7 @@ pipeline { } stage("Build for Windows 32-bit") { agent { - label "untrusted" + label "built-in" } steps { sh("git clean -dfx") @@ -51,7 +51,7 @@ pipeline { } stage("Build for Windows 64-bit") { agent { - label "untrusted" + label "built-in" } steps { sh("git clean -dfx") @@ -76,7 +76,7 @@ pipeline { } stage("Build for Windows 32-bit (Watcom)") { agent { - label "untrusted" + label "built-in" } steps { sh("git clean -dfx") From 979e5e056de063d58c0f52bf062114f6db3cd0cd Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 07:30:04 +0900 Subject: [PATCH 105/168] ok --- Jenkinsfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 8e42285..9b7d639 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -78,6 +78,11 @@ pipeline { agent { label "built-in" } + environment { + WATCOM = "/usr/watcom" + INCLUDE = "/usr/watcom/h:/usr/watcom/h/nt" + PATH = "/usr/watcom/binl64:${env.PATH}" + } steps { sh("git clean -dfx") sh("wmake -f WatMakefile") From e5255bcbfa01cc69df47094fdab8da9d7f6ec06d Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 07:39:29 +0900 Subject: [PATCH 106/168] fix dnd --- examples/basic/dnd.c | 1 + milsko.xml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/examples/basic/dnd.c b/examples/basic/dnd.c index f88a650..0a2495e 100644 --- a/examples/basic/dnd.c +++ b/examples/basic/dnd.c @@ -40,6 +40,7 @@ int main() { window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 400, 400, MwNtitle, "dnd", + MwNacceptsDnD, 1, NULL); instructions = MwVaCreateWidget(MwLabelClass, "button", window, 50, 50, 300, 125, MwNtext, "drag a file and its name will show up below.", diff --git a/milsko.xml b/milsko.xml index ec30e82..7ac33f1 100644 --- a/milsko.xml +++ b/milsko.xml @@ -107,6 +107,7 @@ + @@ -197,6 +198,9 @@ + + + From fdbdc83527a6bb2a77f60d00451b5130942b5df8 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 15 Sep 2026 09:45:38 +0900 Subject: [PATCH 107/168] better wayland clipboard, initial xdnd support --- examples/basic/dnd.c | 44 +++---- include/Mw/LowLevel/Wayland.h | 2 + include/Mw/LowLevel/X11.h | 44 ++++--- src/backend/wayland/interfaces.c | 80 +++++++++++- src/backend/wayland/wayland.c | 2 +- src/backend/x11.c | 208 +++++++++++++++++++++++++++++-- 6 files changed, 322 insertions(+), 58 deletions(-) diff --git a/examples/basic/dnd.c b/examples/basic/dnd.c index 0a2495e..8d0f47d 100644 --- a/examples/basic/dnd.c +++ b/examples/basic/dnd.c @@ -1,6 +1,6 @@ #include -MwWidget window, instructions, text1, cur_text; +MwWidget window, box, instructions, cur_text, text_listbox; static void MWAPI resize(MwWidget handle, void* user_data, void* call_data) { unsigned int w, h; @@ -11,17 +11,7 @@ static void MWAPI resize(MwWidget handle, void* user_data, void* call_data) { w = MwGetInteger(handle, MwNwidth); h = MwGetInteger(handle, MwNheight); - MwVaApply(instructions, - MwNy, 50, - MwNwidth, w - 50 * 2, - MwNheight, h - 125 - 50 * 3, - NULL); - - MwVaApply(text1, - MwNy, 150, - MwNwidth, w - 25 * 2, - MwNheight, h - 125 - 50 * 3, - NULL); + MwVaApply(box, MwNwidth, w, MwNheight, h, NULL); } static void MWAPI dnd(MwWidget handle, void* user_data, void* call_data) { char* filename = call_data; @@ -30,29 +20,35 @@ static void MWAPI dnd(MwWidget handle, void* user_data, void* call_data) { (void)user_data; if(filename != NULL) { - MwVaApply(cur_text, MwNtext, filename, NULL); - MwForceRender(cur_text); + MwListBoxSet(text_listbox, -1, -1, filename); + MwForceRender(text_listbox); } } int main() { - MwLibraryInit(); + MwSizeHints hints; - window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 400, 400, - MwNtitle, "dnd", + MwLibraryInit(); + hints.min_width = hints.min_height = 600; + + window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 600, 600, + MwNtitle, "dnd", + MwNsizeHints, &hints, + NULL); + + box = MwVaCreateWidget(MwBoxClass, NULL, window, 0, 0, 800, 800, MwNorientation, MwVERTICAL, MwNpadding, 25, NULL); + + instructions = MwVaCreateWidget(MwLabelClass, "button", box, 50, 50, 750, 50, + MwNtext, "drag files onto this text box, and their names will show up below.", MwNacceptsDnD, 1, NULL); - instructions = MwVaCreateWidget(MwLabelClass, "button", window, 50, 50, 300, 125, - MwNtext, "drag a file and its name will show up below.", - NULL); - text1 = MwVaCreateWidget(MwLabelClass, "label", window, 25, 150, 300, 75, + text_listbox = MwVaCreateWidget(MwListBoxClass, "label", box, 25, 150, 750, 700, MwNtext, "", + MwNacceptsDnD, 1, NULL); - cur_text = text1; - MwAddUserHandler(window, MwNresizeHandler, resize, NULL); - MwAddUserHandler(window, MwNdragAndDropHandler, dnd, NULL); + MwAddUserHandler(instructions, MwNdragAndDropHandler, dnd, NULL); resize(window, NULL, NULL); diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 44a3983..7a2c25c 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -456,6 +456,8 @@ struct _MwLLWayland { MwU64 next_elapsed; long start_time; long end_time; + + MwBool accepts_dnd; }; struct _MwLLWaylandColor { diff --git a/include/Mw/LowLevel/X11.h b/include/Mw/LowLevel/X11.h index e1b7416..9663097 100644 --- a/include/Mw/LowLevel/X11.h +++ b/include/Mw/LowLevel/X11.h @@ -27,20 +27,36 @@ struct _MwLLX11 { unsigned int width; unsigned int height; - Display* display; - Window window; - Pixmap pixmap; - GC gc; - Colormap colormap; - Atom wm_delete; - Atom wm_protocols; - Atom utf8_string; - Atom compound_text; - Atom text; - Atom clipboard; - Atom selection; - XIM xim; - XIC xic; + Display* display; + Window window; + Pixmap pixmap; + GC gc; + Colormap colormap; + Atom wm_delete; + Atom wm_protocols; + Atom utf8_string; + Atom compound_text; + Atom text; + Atom clipboard; + Atom selection; + Atom xdnd_type_list; + Atom xdnd_selection; + Atom xdnd_enter; + Atom xdnd_position; + Atom xdnd_status; + Atom xdnd_leave; + Atom xdnd_drop; + Atom xdnd_finished; + Atom xdnd_action_copy; + Atom xdnd_text_uri_list; + Atom xdnd_text_plain; + Atom xdnd_aware; + int xdnd_source; + unsigned char xdnd_version; + int xdnd_format; + + XIM xim; + XIC xic; long clipboard_time; int clipboard_pending; /* 1 if UTF8_STRING, 2 if COMPOUND_TEXT, 3 if TEXT, 4 if STRING, otherwise 0 */ diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index eaabf16..dd58f9a 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -19,6 +19,7 @@ static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat); static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); +static bool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos); /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { @@ -168,6 +169,57 @@ static void wl_data_device_leave(void* data, self->offer.wl = NULL; } }; + +static MwBool motion_cursor_change(MwLL self, wl_clipboard_device_context_t* ctx) { + if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) { + return MwTRUE; + } else if(self->common.user) { + MwWidget w = self->common.user; + int i, n; + for(i = 0; i < arrlen(w->children); i++) { + if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { + MwLL child = w->children[i]->lowlevel; + MwLL topmost_parent = child; + MwPoint point; + MwPoint relative_mouse_pos; + MwPoint absolute_pos; + + if(hit_detect(child, &topmost_parent, &point, &relative_mouse_pos, &absolute_pos)) { + return MwTRUE; + } else { + return motion_cursor_change(child, ctx); + } + } + } + } + return MwFALSE; +} + +static void clipboard_dispatch(MwLL self, char* buf) { + if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) { + MwLLDispatch(self, drag_and_drop, buf); + } else if(self->common.user) { + MwWidget w = self->common.user; + int i, n; + for(i = 0; i < arrlen(w->children); i++) { + if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { + MwLL child = w->children[i]->lowlevel; + MwLL topmost_parent = child; + MwPoint point; + MwPoint relative_mouse_pos; + MwPoint absolute_pos; + + if(hit_detect(child, &topmost_parent, &point, &relative_mouse_pos, &absolute_pos) && child->wayland.accepts_dnd) { + MwLLDispatch(child, drag_and_drop, buf); + return; + } else { + clipboard_dispatch(child, buf); + } + } + } + } +} + static void wl_data_device_motion(void* data, struct wl_data_device* wl_data_device, uint32_t time, @@ -179,8 +231,15 @@ static void wl_data_device_motion(void* data, (void)y; wl_clipboard_device_context_t* self = data; + self->ll->wayland.cur_mouse_pos.x = wl_fixed_to_int(x); + self->ll->wayland.cur_mouse_pos.y = wl_fixed_to_int(y); + if(self->selected_mime_type[0] != '\0' && self->offer.wl) { - wl_data_offer_set_actions(self->offer.wl, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); + if(motion_cursor_change(self->ll, self)) { + wl_data_offer_set_actions(self->offer.wl, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); + } else { + wl_data_offer_set_actions(self->offer.wl, WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE, WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE); + }; } }; static void wl_data_device_drop(void* data, @@ -193,7 +252,6 @@ static void wl_data_device_drop(void* data, int rc = 0; if(pipe(fds) != 0) { - return; } @@ -226,10 +284,20 @@ static void wl_data_device_drop(void* data, setup_clipboard(self->ll, self->ll->wayland.pointer_seat); - if(strstr(buf, "file://")) { - MwLLDispatch(self->ll, drag_and_drop, buf + sizeof("file://") - 1); - } else { - MwLLDispatch(self->ll, drag_and_drop, buf); + char* buf_ptr = buf; + while(buf_ptr) { + char* next = strstr(buf_ptr, "\n"); + if(next) { + *next = '\0'; + if(strstr(buf_ptr, "file://")) { + clipboard_dispatch(self->ll, buf_ptr + sizeof("file://") - 1); + } else { + clipboard_dispatch(self->ll, buf_ptr); + } + buf_ptr = next + 1; + } else { + buf_ptr = NULL; + } } arrfree(buf); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 6154664..bd17f84 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1794,7 +1794,6 @@ static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { } static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { - rect->x = 0; rect->y = 0; rect->width = handle->wayland.mw; @@ -1803,6 +1802,7 @@ static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { static void MwLLSetupDragAndDropImpl(MwLL handle) { (void)handle; + handle->wayland.accepts_dnd = MwTRUE; } static void MwLLBeginStateChangeImpl(MwLL handle) { diff --git a/src/backend/x11.c b/src/backend/x11.c index 8b908e4..eaa64e0 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -82,6 +82,8 @@ static struct symtbl { void (*XSetICFocus)(XIC); XImage* (*XGetImage)(Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int); int (*XRaiseWindow)(Display*, Window); + int (*XFlush)(Display*); + char* (*XGetAtomName)(Display*, Atom); XSizeHints* (*XAllocSizeHints)(void); XVisualInfo* (*XGetVisualInfo)(Display*, long, XVisualInfo*, int*); @@ -186,6 +188,8 @@ static struct symtbl { #define XChangeWindowAttributes xsymtbl.XChangeWindowAttributes #define XGetImage xsymtbl.XGetImage #define XRaiseWindow xsymtbl.XRaiseWindow +#define XFlush xsymtbl.XFlush +#define XGetAtomName xsymtbl.XGetAtomName #if USE_XRENDER #define XRenderFindStandardFormat xsymtbl.XRenderFindStandardFormat @@ -425,6 +429,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->x11.colormap = DefaultColormap(r->x11.display, XDefaultScreen(r->x11.display)); r->x11.wm_delete = XInternAtom(r->x11.display, "WM_DELETE_WINDOW", False); r->x11.wm_protocols = XInternAtom(r->x11.display, "WM_PROTOCOLS", False); + XSetWMProtocols(r->x11.display, r->x11.window, &r->x11.wm_delete, 1); r->x11.utf8_string = XInternAtom(r->x11.display, "UTF8_STRING", False); @@ -433,6 +438,21 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->x11.clipboard = XInternAtom(r->x11.display, "CLIPBOARD", False); r->x11.selection = XInternAtom(r->x11.display, "_MILSKO_SELECTION_", False); + r->x11.xdnd_type_list = XInternAtom(r->x11.display, "XdndTypeList", False); + r->x11.xdnd_selection = XInternAtom(r->x11.display, "XdndSelection", False); + r->x11.xdnd_enter = XInternAtom(r->x11.display, "XdndEnter", False); + r->x11.xdnd_position = XInternAtom(r->x11.display, "XdndPosition", False); + r->x11.xdnd_status = XInternAtom(r->x11.display, "XdndStatus", False); + r->x11.xdnd_leave = XInternAtom(r->x11.display, "XdndLeave", False); + r->x11.xdnd_drop = XInternAtom(r->x11.display, "XdndDrop", False); + r->x11.xdnd_finished = XInternAtom(r->x11.display, "XdndFinished", False); + r->x11.xdnd_action_copy = XInternAtom(r->x11.display, "XdndActionCopy", False); + r->x11.xdnd_text_uri_list = XInternAtom(r->x11.display, "text/uri-list", False); + r->x11.xdnd_text_plain = XInternAtom(r->x11.display, "text/plain", False); + r->x11.xdnd_aware = XInternAtom(r->x11.display, "XdndAware", False); + r->x11.xdnd_version = 5; + r->x11.xdnd_format = None; + r->x11.clipboard_pending = 0; r->x11.gc = XCreateGC(r->x11.display, r->x11.window, 0, NULL); @@ -704,10 +724,15 @@ static void MwLLNextEventImpl(MwLL handle) { while(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, SelectionNotify, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) { int render = 0; - if(ev.type == Expose) { + switch(ev.type) { + case Expose: + { handle->x11.force_render = 0; render = 1; - } else if(ev.type == ButtonPress) { + break; + }; + case ButtonPress: + { MwMouse p; p.point.x = ev.xbutton.x; p.point.y = ev.xbutton.y; @@ -728,7 +753,10 @@ static void MwLLNextEventImpl(MwLL handle) { #endif MwLLDispatch(handle, down, &p); - } else if(ev.type == ButtonRelease) { + break; + }; + case ButtonRelease: + { MwMouse p; p.point.x = ev.xbutton.x; p.point.y = ev.xbutton.y; @@ -745,24 +773,122 @@ static void MwLLNextEventImpl(MwLL handle) { } MwLLDispatch(handle, up, &p); - } else if(ev.type == ConfigureNotify) { + break; + }; + case ConfigureNotify: + { if(handle->x11.width != (unsigned int)ev.xconfigure.width || handle->x11.height != (unsigned int)ev.xconfigure.height) { MwLLDispatch(handle, resize, NULL); destroy_pixmap(handle); create_pixmap(handle); render = 1; + break; } handle->x11.width = ev.xconfigure.width; handle->x11.height = ev.xconfigure.height; - } else if(ev.type == ClientMessage) { + }; + case ClientMessage: + { + if(ev.xclient.message_type == handle->x11.wm_protocols && ev.xclient.data.l[0] == (long)handle->x11.wm_delete) { MwLLDispatch(handle, close, NULL); } - } else if(ev.type == FocusIn) { + + if( + ev.xclient.message_type == handle->x11.xdnd_enter || + ev.xclient.message_type == handle->x11.xdnd_position || + ev.xclient.message_type == handle->x11.xdnd_drop) { + char* name = XGetAtomName(handle->x11.display, ev.xclient.message_type); + + if(ev.xclient.message_type == handle->x11.xdnd_enter) { + Bool list = ev.xclient.data.l[1] & 1; + int version = ev.xclient.data.l[1] >> 24; + unsigned long count = 0; + unsigned char* formats = NULL; + unsigned long i; + handle->x11.xdnd_source = ev.xclient.data.l[0]; + if(list) { + Atom actualType; + int32_t actualFormat; + unsigned long bytesAfter; + + XGetWindowProperty((Display*)handle->x11.display, + handle->x11.xdnd_source, + handle->x11.xdnd_type_list, + 0, + LONG_MAX, + False, + 4, + &actualType, + &actualFormat, + &count, + &bytesAfter, + (unsigned char**)&formats); + } else { + count = 0; + + if(ev.xclient.data.l[2] != None) + formats[count++] = ev.xclient.data.l[2]; + if(ev.xclient.data.l[3] != None) + formats[count++] = ev.xclient.data.l[3]; + if(ev.xclient.data.l[4] != None) + formats[count++] = ev.xclient.data.l[4]; + } + + for(i = 0; i < count; i++) { + if(formats[i] == handle->x11.xdnd_text_uri_list || formats[i] == handle->x11.xdnd_text_plain) { + handle->x11.xdnd_format = formats[i]; + printf("format %d\n", handle->x11.xdnd_format); + break; + } + } + + if(list) { + XFree(formats); + } + } + if(ev.xclient.message_type == handle->x11.xdnd_position && handle->x11.xdnd_version >= 5) { + XEvent reply; + reply.xclient.message_type = handle->x11.xdnd_status; + + if(handle->x11.xdnd_format) { + reply.xclient.data.l[1] = 1; + if(handle->x11.xdnd_version >= 2) reply.xclient.data.l[4] = handle->x11.xdnd_action_copy; + } + XSendEvent(handle->x11.display, handle->x11.xdnd_source, False, NoEventMask, &reply); + XFlush(handle->x11.display); + } + if(ev.xclient.message_type == handle->x11.xdnd_drop && handle->x11.xdnd_version >= 5) { + Time time = CurrentTime; + if(handle->x11.xdnd_version >= 1) + time = ev.xclient.data.l[2]; + + if(handle->x11.xdnd_format) { + XConvertSelection((Display*)handle->x11.display, + handle->x11.xdnd_selection, + handle->x11.xdnd_format, + handle->x11.xdnd_selection, + (Window)handle->x11.window, + time); + } + } + + XFree(name); + } + break; + }; + case FocusIn: + { MwLLDispatch(handle, focus_in, NULL); - } else if(ev.type == FocusOut) { + break; + }; + case FocusOut: + { MwLLDispatch(handle, focus_out, NULL); - } else if(ev.type == MotionNotify) { + break; + }; + case MotionNotify: + { MwPoint p; XWindowAttributes attr; @@ -780,7 +906,11 @@ static void MwLLNextEventImpl(MwLL handle) { if(handle->x11.grabbed && (p.x != 0 || p.y != 0)) { XWarpPointer(handle->x11.display, None, handle->x11.window, 0, 0, 0, 0, attr.width / 2, attr.height / 2); } - } else if(ev.type == KeyPress || ev.type == KeyRelease) { + break; + }; + case KeyPress: + case KeyRelease: + { int n = -1; char str[512]; KeySym sym; @@ -844,10 +974,60 @@ static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, key_released, &n); } } - } else if(ev.type == SelectionNotify) { + break; + }; + case SelectionNotify: + { handle->x11.clipboard_pending = 0; - if(ev.xselection.property != None) { + if(ev.xselection.property == handle->x11.xdnd_selection) { + XEvent reply; + char* data; + unsigned long result; + Atom actualType; + int32_t actualFormat; + unsigned long bytesAfter; + + XGetWindowProperty(handle->x11.display, + ev.xselection.requestor, ev.xselection.property, + 0, LONG_MAX, False, ev.xselection.target, + &actualType, &actualFormat, &result, &bytesAfter, + (unsigned char**)&data); + + if(result == 0) + break; + + /* !! untested lmao !! */ + printf("File(s) dropped: %s\n", data); + char* data_ptr = data; + while(data_ptr) { + char* next = strstr(data, "\n"); + if(next) *next = '\0'; + + printf("%s\n", data_ptr); + + if(strstr(data_ptr, "file://")) { + MwLLDispatch(handle, drag_and_drop, data_ptr + sizeof("file://") - 1); + } else { + MwLLDispatch(handle, drag_and_drop, data_ptr); + } + if(next) data_ptr = next + 1; + else + data_ptr = NULL; + } + + if(data) + XFree(data); + + if(handle->x11.xdnd_version >= 2) { + reply.xclient.message_type = handle->x11.xdnd_finished; + reply.xclient.data.l[1] = result; + reply.xclient.data.l[2] = handle->x11.xdnd_action_copy; + + XSendEvent((Display*)handle->x11.display, handle->x11.xdnd_source, False, NoEventMask, &reply); + XFlush((Display*)handle->x11.display); + } + } else if(ev.xselection.property != None) { Atom type; int format; unsigned long nitems, after, size; @@ -884,9 +1064,9 @@ static void MwLLNextEventImpl(MwLL handle) { free(buf); } } - XDeleteProperty(handle->x11.display, handle->x11.window, handle->x11.selection); } + } break; } if(render) { int x, y; @@ -1365,7 +1545,7 @@ static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { } static void MwLLSetupDragAndDropImpl(MwLL handle) { - (void)handle; + XChangeProperty(handle->x11.display, handle->x11.window, handle->x11.xdnd_aware, 4, 32, PropModeReplace, &handle->x11.xdnd_version, 1); } static void MwLLBeginStateChangeImpl(MwLL handle) { @@ -1512,6 +1692,8 @@ static int MwLLX11CallInitImpl(void) { X11_FUNC_LOAD(XSetICFocus); X11_FUNC_LOAD(XGetImage); X11_FUNC_LOAD(XRaiseWindow); + X11_FUNC_LOAD(XFlush); + X11_FUNC_LOAD(XGetAtomName); X11_FUNC_LOAD(XAllocSizeHints); X11_FUNC_LOAD(XGetVisualInfo); From 097e11244ccffd618c8d05a28555c50f5cd88baf Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 11:58:16 +0900 Subject: [PATCH 108/168] somewhat functional --- examples/basic/document.c | 27 ++- include/Mw/Constants.h | 10 + include/Mw/StringDefs.h | 2 +- include/Mw/TypeDefs.h | 19 ++ milsko.xml | 12 +- src/widget/document.c | 437 +++++++++++++++++++++++++++++++++++++- 6 files changed, 490 insertions(+), 17 deletions(-) diff --git a/examples/basic/document.c b/examples/basic/document.c index e53339c..a9482a8 100644 --- a/examples/basic/document.c +++ b/examples/basic/document.c @@ -12,10 +12,22 @@ static void MWAPI resize_window(MwWidget handle, void* user, void* call) { MwNwidth, width - 20, MwNheight, height - 20, NULL); + + width = MwGetInteger(MwGetParent(MwViewportGetViewport(viewport)), MwNwidth); + height = MwGetInteger(MwGetParent(MwViewportGetViewport(viewport)), MwNheight); + + MwVaApply(document, + MwNwidth, width, + NULL); } -static void MWAPI resize_document(MwWidget handle, void* user, void* call) { - MwViewportSetSize(viewport, MwGetInteger(document, MwNwidth), MwGetInteger(document, MwNheight)); +static void MWAPI layout_document(MwWidget handle, void* user, void* call) { + int height = *(int*)call; + + MwViewportSetSize(viewport, MwGetInteger(document, MwNwidth), height); + MwVaApply(document, + MwNheight, height, + NULL); } int main() { @@ -27,17 +39,14 @@ int main() { viewport = MwCreateWidget(MwViewportClass, "viewport", window, 0, 0, 0, 0); - MwVaApply(MwGetParent(MwViewportGetViewport(viewport)), - MwNbackground, "#fff", - MwNforeground, "#000", - NULL); - document = MwVaCreateWidget(MwDocumentClass, "document", MwViewportGetViewport(viewport), 0, 0, 0, 0, - MwNtext, "# Hello world!\nThis is a test text...", + MwNtext, "# Hello world!\nThis is a __test__ text...\n\n`Some monospace here`\n\n~~Removed~~\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + MwNbackground, "#fff", + MwNforeground, "#000", NULL); MwAddUserHandler(window, MwNresizeHandler, resize_window, NULL); - MwAddUserHandler(document, MwNresizeHandler, resize_document, NULL); + MwAddUserHandler(document, MwNlayoutHandler, layout_document, NULL); resize_window(window, NULL, NULL); diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index acd6b05..bbef56c 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -121,6 +121,16 @@ enum MwCHART { MwCHART_LINE }; +enum MwDOCUMENT_LAYOUT { + MwDOCUMENT_TEXT = 0, + MwDOCUMENT_NEWLINE, + MwDOCUMENT_HEADER, + MwDOCUMENT_BOLD, + MwDOCUMENT_MONOSPACE, + MwDOCUMENT_STRIKETHROUGH, + MwDOCUMENT_UNDERLINE, +}; + enum MwMOUSE { MwMOUSE_LEFT = 1, MwMOUSE_MIDDLE, diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 71b8f5f..b3f527b 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -58,7 +58,6 @@ #define MwNminute "Iminute" #define MwNsecond "Isecond" #define MwNtype "Itype" -#define MwNautoResize "IautoResize" #define MwNtitle "Stitle" #define MwNtext "Stext" @@ -105,5 +104,6 @@ #define MwNclipboardHandler "Cclipboard" #define MwNdarkThemeHandler "CdarkTheme" #define MwNdragAndDropHandler "CdragAndDrop" +#define MwNlayoutHandler "Clayout" #endif diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 0be60e8..2a11d36 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -32,6 +32,8 @@ typedef struct _MwTab* MwTab; typedef struct _MwTable* MwTable; typedef struct _MwChartEntry MwChartEntry; typedef struct _MwChart* MwChart; +typedef struct _MwDocumentLayout MwDocumentLayout; +typedef struct _MwDocument* MwDocument; typedef struct _MwMouse MwMouse; typedef struct _MwTTFInfo* MwTTFInfo; #ifdef _MILSKO @@ -264,6 +266,23 @@ struct _MwMouse { int button; }; +struct _MwDocumentLayout { + int type; + + int x; + int y; + + char* text; + int integer; + + MwFLFont font; +}; + +struct _MwDocument { + MwDocumentLayout* layouts; + MwFLFont headers[6]; +}; + struct _MwTTFInfo { char* family; int weight; diff --git a/milsko.xml b/milsko.xml index 7ac33f1..b864efc 100644 --- a/milsko.xml +++ b/milsko.xml @@ -112,7 +112,6 @@ - @@ -201,6 +200,9 @@ + + + @@ -702,6 +704,14 @@
    + + + + + + + + diff --git a/src/widget/document.c b/src/widget/document.c index 4c5414a..3f83646 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -1,16 +1,62 @@ #include #include "../../external/md4c.h" +#include "../../external/stb_ds.h" + +#define IsFontChange(x) ((x) == MwDOCUMENT_HEADER || (x) == MwDOCUMENT_BOLD || (x) == MwDOCUMENT_MONOSPACE || (x) == MwDOCUMENT_STRIKETHROUGH) + +static void reset(MwWidget handle) { + MwDocument d = handle->internal; + int i; + + for(i = 0; i < arrlen(d->layouts); i++) { + if(d->layouts[i].text != NULL) free(d->layouts[i].text); + } + arrfree(d->layouts); +} static int wcreate(MwWidget handle) { + MwDocument d = malloc(sizeof(*d)); + int i; + + memset(d, 0, sizeof(*d)); + + for(i = 0; i < 6; i++) { + d->headers[i] = MwFLFontLoad == NULL ? NULL : MwFLFontLoad(MwBoldTTFData, MwBoldTTFDataSize, 13 + 2 * (6 - i)); + } + + handle->internal = d; + MwSetDefault(handle); return 0; } +static void destroy(MwWidget handle) { + MwDocument d = handle->internal; + int i; + + reset(handle); + + for(i = 0; i < 6; i++) { + if(d->headers[i] != NULL) MwFLFontFree(d->headers[i]); + } + + free(handle->internal); +} + static void draw(MwWidget handle) { - MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); - MwRect r; + MwDocument d = handle->internal; + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwRect r; + int i; + MwFLFont font = NULL; + MwPoint u_p, s_p; + int u = 0, s = 0; + + u_p.x = u_p.y = 0; + s_p.x = s_p.y = 0; r.x = 0; r.y = 0; @@ -18,21 +64,400 @@ static void draw(MwWidget handle) { r.height = MwGetInteger(handle, MwNheight); MwDrawRect(handle, &r, base); + for(i = 0; i < arrlen(d->layouts); i++) { + MwDocumentLayout* l = &d->layouts[i]; + + switch(l->type) { + case MwDOCUMENT_TEXT: + { + MwPoint p; + + p.x = l->x; + p.y = l->y + MwTextHeight(handle, font, l->text) / 2; + + MwDrawText(handle, font, &p, l->text, MwALIGNMENT_BEGINNING, text); + + if(u || s) { + MwPoint line[2]; + int j; + + if(u_p.y != l->y) { + u_p.x = 0; + u_p.y = l->y; + } + + line[0] = u_p; + line[1] = u_p; + + line[1].x = p.x + MwTextWidth(handle, font, l->text); + u_p.x = line[1].x; + + for(j = 0; j < 2; j++) { + line[0].y += MwTextHeight(handle, font, l->text) / 2; + line[1].y += MwTextHeight(handle, font, l->text) / 2; + if((j == 0 && s) || (j == 1 && u)) MwLLLine(handle->lowlevel, line, text); + } + } + break; + } + case MwDOCUMENT_UNDERLINE: + case MwDOCUMENT_STRIKETHROUGH: + { + if(l->type == MwDOCUMENT_UNDERLINE) { + u = l->integer; + } else { + s = l->integer; + } + + if(l->type == MwDOCUMENT_UNDERLINE ? u : s) { + int j; + + for(j = i + 1; j < arrlen(d->layouts) && d->layouts[j].type != l->type; j++) { + if(d->layouts[j].type == MwDOCUMENT_TEXT) { + MwPoint p; + + p.x = d->layouts[j].x; + p.y = d->layouts[j].y; + + if(l->type == MwDOCUMENT_UNDERLINE) { + u_p = p; + } else { + s_p = p; + } + break; + } + } + } + break; + } + default: + break; + } + + if(IsFontChange(l->type)) font = l->font; + } + + MwLLFreeColor(text); MwLLFreeColor(base); } +static int enter_block(MD_BLOCKTYPE type, void* detail, void* userdata) { + MwDocument d = userdata; + MwDocumentLayout l; + + memset(&l, 0, sizeof(l)); + + switch(type) { + case MD_BLOCK_H: + { + l.type = MwDOCUMENT_HEADER; + l.integer = ((MD_BLOCK_H_DETAIL*)detail)->level; + + arrput(d->layouts, l); + break; + } + default: + break; + } + + return 0; +} + +static int leave_block(MD_BLOCKTYPE type, void* detail, void* userdata) { + MwDocument d = userdata; + MwDocumentLayout l; + + (void)detail; + + memset(&l, 0, sizeof(l)); + + switch(type) { + case MD_BLOCK_H: + { + l.type = MwDOCUMENT_HEADER; + l.integer = 0; + + arrput(d->layouts, l); + break; + } + case MD_BLOCK_P: + { + l.type = MwDOCUMENT_NEWLINE; + + arrput(d->layouts, l); + break; + } + default: + break; + } + + return 0; +} + +static int enter_span(MD_SPANTYPE type, void* detail, void* userdata) { + MwDocument d = userdata; + MwDocumentLayout l; + + (void)detail; + + memset(&l, 0, sizeof(l)); + + switch(type) { + case MD_SPAN_STRONG: + { + l.type = MwDOCUMENT_BOLD; + l.integer = 1; + + arrput(d->layouts, l); + break; + } + case MD_SPAN_U: + { + l.type = MwDOCUMENT_UNDERLINE; + l.integer = 1; + + arrput(d->layouts, l); + break; + } + case MD_SPAN_CODE: + { + l.type = MwDOCUMENT_MONOSPACE; + l.integer = 1; + + arrput(d->layouts, l); + break; + } + case MD_SPAN_DEL: + { + l.type = MwDOCUMENT_STRIKETHROUGH; + l.integer = 1; + + arrput(d->layouts, l); + break; + } + default: + break; + } + + return 0; +} + +static int leave_span(MD_SPANTYPE type, void* detail, void* userdata) { + MwDocument d = userdata; + MwDocumentLayout l; + + (void)detail; + + memset(&l, 0, sizeof(l)); + + switch(type) { + case MD_SPAN_STRONG: + { + l.type = MwDOCUMENT_BOLD; + l.integer = 0; + + arrput(d->layouts, l); + break; + } + case MD_SPAN_U: + { + l.type = MwDOCUMENT_UNDERLINE; + l.integer = 0; + + arrput(d->layouts, l); + break; + } + case MD_SPAN_CODE: + { + l.type = MwDOCUMENT_MONOSPACE; + l.integer = 0; + + arrput(d->layouts, l); + break; + } + case MD_SPAN_DEL: + { + l.type = MwDOCUMENT_STRIKETHROUGH; + l.integer = 0; + + arrput(d->layouts, l); + break; + } + default: + break; + } + + return 0; +} + +static int text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata) { + MwDocument d = userdata; + MwDocumentLayout l; + + memset(&l, 0, sizeof(l)); + + switch(type) { + case MD_TEXT_NORMAL: + case MD_TEXT_CODE: + { + char* str = malloc(size + 1); + char* begin = str; + char* next; + + memcpy(str, text, size); + str[size] = 0; + + do { + next = strchr(str, ' '); + if(next != NULL) next[0] = 0; + + if(strlen(str) > 0) { + memset(&l, 0, sizeof(l)); + + l.type = MwDOCUMENT_TEXT; + l.text = MwStringDuplicate(str); + + arrput(d->layouts, l); + } + + str = next + 1; + } while(next != NULL); + + free(begin); + break; + } + case MD_TEXT_BR: + { + l.type = MwDOCUMENT_NEWLINE; + + arrput(d->layouts, l); + break; + } + default: + break; + } + + return 0; +} + +#define TOPFONT fontstack[arrlen(fontstack) - 1] +#define POP arrdel(fontstack, arrlen(fontstack) - 1); + +static void layout(MwWidget handle) { + MwDocument d = handle->internal; + int w = MwGetInteger(handle, MwNwidth); + int i; + int x = 0; + int y = 0; + MwFLFont* fontstack = NULL; + + arrput(fontstack, NULL); + + for(i = 0; i < arrlen(d->layouts); i++) { + MwDocumentLayout* l = &d->layouts[i]; + + switch(l->type) { + case MwDOCUMENT_TEXT: + { + int t = MwTextWidth(handle, TOPFONT, l->text); + + if(x > 0) x += MwTextWidth(handle, TOPFONT, " "); + + if((x + t) >= w) { + x = 0; + y += MwTextHeight(handle, TOPFONT, "M"); + } + + l->x = x; + l->y = y; + + x += t; + break; + } + case MwDOCUMENT_NEWLINE: + { + x = 0; + y += MwTextHeight(handle, TOPFONT, "M"); + break; + } + case MwDOCUMENT_BOLD: + { + if(l->integer) { + MwFLFont f = (void*)((size_t)(TOPFONT) | MwFLFlagBold); + + arrput(fontstack, f); + } else { + POP; + } + break; + } + case MwDOCUMENT_MONOSPACE: + { + if(l->integer) { + MwFLFont f = (void*)((size_t)(TOPFONT) | MwFLFlagMonospace); + + arrput(fontstack, f); + } else { + POP; + } + break; + } + case MwDOCUMENT_HEADER: + { + if(l->integer) { + arrput(fontstack, d->headers[l->integer - 1]); + } else { + x = 0; + y += MwTextHeight(handle, TOPFONT, "M"); + + POP; + } + break; + } + } + + l->font = TOPFONT; + } + + y += MwTextHeight(handle, TOPFONT, "M"); + MwDispatchUserHandler(handle, MwNlayoutHandler, &y); + + arrfree(fontstack); + + MwForceRender(handle); +} + static void prop_change(MwWidget handle, const char* key) { - if(strcmp(key, MwNautoResize) == 0 || strcmp(key, MwNtext) == 0) MwForceRender(handle); + if(strcmp(key, MwNtext) == 0) MwForceRender(handle); if(strcmp(key, MwNtext) == 0) { - MD_PARSER parser; + MD_PARSER parser; + const char* str = MwGetText(handle, MwNtext); + memset(&parser, 0, sizeof(parser)); + + parser.flags = MD_FLAG_UNDERLINE | MD_FLAG_STRIKETHROUGH; + parser.enter_block = enter_block; + parser.leave_block = leave_block; + parser.enter_span = enter_span; + parser.leave_span = leave_span; + parser.text = text; + + reset(handle); + + md_parse(str, strlen(str), &parser, handle->internal); + + layout(handle); } } +static void resize(MwWidget handle) { + layout(handle); +} + MwClassRec MwDocumentClassRec = { wcreate, /* create */ - NULL, /* destroy */ + destroy, /* destroy */ draw, /* draw */ NULL, /* click */ NULL, /* parent_resize */ @@ -43,7 +468,7 @@ MwClassRec MwDocumentClassRec = { NULL, /* key */ NULL, /* execute */ NULL, /* tick */ - NULL, /* resize */ + resize, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ NULL, /* clipboard */ From 3922213bebb21ec39bf70e6fa3ac5a8686f47c2e Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 12:01:53 +0900 Subject: [PATCH 109/168] fix --- examples/basic/periodic.c | 4 ++-- include/Mw/Constants.h | 4 ++-- milsko.xml | 4 ++-- src/widget/chart.c | 20 ++++++++++---------- src/widget/combobox.c | 2 -- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index f7148da..fb2fbd9 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -269,7 +269,7 @@ int main() { wclock = child(f); f = frame("3D Bar Chart", -PaddingContent, -PaddingContent, MwChartClass, - MwNtype, MwCHART_3D_BAR, + MwNtype, MwCHART_BAR_3D, NULL); w = child(f); MwChartAdd(w, -1, "A", -800, NULL); @@ -282,7 +282,7 @@ int main() { MwChartAdd(w, -1, "H", 800, NULL); f = frame("3D Pie Chart", -PaddingContent, -PaddingContent, MwChartClass, - MwNtype, MwCHART_3D_PIE, + MwNtype, MwCHART_PIE_3D, NULL); w = child(f); MwChartAdd(w, -1, "A", 10, NULL); diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index bbef56c..ed77ab5 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -115,9 +115,9 @@ enum MwCLIPBOARD { enum MwCHART { MwCHART_BAR = 0, - MwCHART_3D_BAR, + MwCHART_BAR_3D, MwCHART_PIE, - MwCHART_3D_PIE, + MwCHART_PIE_3D, MwCHART_LINE }; diff --git a/milsko.xml b/milsko.xml index b864efc..1bb19fd 100644 --- a/milsko.xml +++ b/milsko.xml @@ -239,9 +239,9 @@
    0 - + - + 1 diff --git a/src/widget/chart.c b/src/widget/chart.c index 67753c9..40e760d 100644 --- a/src/widget/chart.c +++ b/src/widget/chart.c @@ -44,7 +44,7 @@ static void draw_line(MwWidget handle, const char* text, double x, double y, dou p[1].y = p[0].y; MwDrawText(handle, NULL, p, text, MwALIGNMENT_END, color); - if(type == MwCHART_3D_BAR) { + if(type == MwCHART_BAR_3D) { MwPoint p2[2]; p2[0] = p[0]; @@ -150,7 +150,7 @@ static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int MwDrawRect(handle, &node, color); - if(type == MwCHART_3D_BAR) { + if(type == MwCHART_BAR_3D) { MwRect node2 = node; MwFixRect(&node2); @@ -195,7 +195,7 @@ static void bar_chart(MwWidget handle, MwRect* _r, double vmin, double vmax, int if(!modern) { MwDrawRectLine(handle, &node, border); - if(type == MwCHART_3D_BAR) { + if(type == MwCHART_BAR_3D) { MwLLLine(handle->lowlevel, &persp_top[0], border); MwLLLine(handle->lowlevel, &persp_top[1], border); MwLLLine(handle->lowlevel, &persp_top[2], border); @@ -231,7 +231,7 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M int k; int type = MwGetInteger(handle, MwNtype); int modern = MwGetInteger(handle, MwNmodernLook); - double vsquish = type == MwCHART_3D_PIE ? 2 : 1; + double vsquish = type == MwCHART_PIE_3D ? 2 : 1; int i; MwPoint p[2]; MwPoint p2[360 + 1 + 1]; @@ -266,7 +266,7 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M count = j + 1; - if((k == 0 || k == 1) && type == MwCHART_3D_PIE) { + if((k == 0 || k == 1) && type == MwCHART_PIE_3D) { int j; MwPoint p3[360 + 1 + 1]; int d = 0; @@ -296,7 +296,7 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M } if(k == 2) { - MwLLPolygon(handle->lowlevel, p2, count, type == MwCHART_3D_PIE ? colorl : color); + MwLLPolygon(handle->lowlevel, p2, count, type == MwCHART_PIE_3D ? colorl : color); } else if(k == 3) { int j; @@ -308,7 +308,7 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M p2[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; p2[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4 / vsquish; - handle->bgcolor = type == MwCHART_3D_PIE ? colorl : color; + handle->bgcolor = type == MwCHART_PIE_3D ? colorl : color; MwDrawText(handle, NULL, p2, c->entries[i].name, MwALIGNMENT_CENTER, border); } @@ -320,7 +320,7 @@ static void pie_chart(MwWidget handle, MwRect* _r, const char** colors, int n, M } } - if(!modern && type == MwCHART_3D_PIE) { + if(!modern && type == MwCHART_PIE_3D) { p[0].x = r.width / 2 - radius / 2; p[0].y = r.height / 2; p[1] = p[0]; @@ -425,11 +425,11 @@ static void draw(MwWidget handle) { switch(type) { case MwCHART_BAR: - case MwCHART_3D_BAR: + case MwCHART_BAR_3D: bar_chart(handle, &r, vmin, vmax, space, colors, n, border); break; case MwCHART_PIE: - case MwCHART_3D_PIE: + case MwCHART_PIE_3D: pie_chart(handle, &r, colors, n, border); break; case MwCHART_LINE: diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 5502a07..a6cb876 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -19,8 +19,6 @@ static int wcreate(MwWidget handle) { } static void destroy(MwWidget handle) { - MwComboBox cb = handle->internal; - MwComboBoxReset(handle); free(handle->internal); } From a87f7813120ec5bf288aa7637eccbf048c9edb1a Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 12:05:02 +0900 Subject: [PATCH 110/168] i love msvc --- examples/basic/document.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/basic/document.c b/examples/basic/document.c index a9482a8..8ae77f4 100644 --- a/examples/basic/document.c +++ b/examples/basic/document.c @@ -31,6 +31,14 @@ static void MWAPI layout_document(MwWidget handle, void* user, void* call) { } int main() { + char* text = malloc(64 * 1024); + int i; + + strcpy(text, "# Hello world!\nThis is a __test__ text...\n\n`Some monospace here`\n\n~~Removed~~"); + for(i = 0; i < 10; i++) { + strcat(text, "\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); + } + MwLibraryInit(); window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 640, 480, @@ -40,7 +48,7 @@ int main() { viewport = MwCreateWidget(MwViewportClass, "viewport", window, 0, 0, 0, 0); document = MwVaCreateWidget(MwDocumentClass, "document", MwViewportGetViewport(viewport), 0, 0, 0, 0, - MwNtext, "# Hello world!\nThis is a __test__ text...\n\n`Some monospace here`\n\n~~Removed~~\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + MwNtext, text, MwNbackground, "#fff", MwNforeground, "#000", NULL); @@ -50,5 +58,7 @@ int main() { resize_window(window, NULL, NULL); + free(text); + MwLoop(window); } From 5d14444de0cb6b1ec77bdcc83262ae603fe4473b Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 15 Sep 2026 12:07:02 +0900 Subject: [PATCH 111/168] looks better --- examples/basic/document.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/basic/document.c b/examples/basic/document.c index 8ae77f4..9bce548 100644 --- a/examples/basic/document.c +++ b/examples/basic/document.c @@ -49,8 +49,6 @@ int main() { document = MwVaCreateWidget(MwDocumentClass, "document", MwViewportGetViewport(viewport), 0, 0, 0, 0, MwNtext, text, - MwNbackground, "#fff", - MwNforeground, "#000", NULL); MwAddUserHandler(window, MwNresizeHandler, resize_window, NULL); From fe371ad89c881416c054e87ce205184fe0dc785b Mon Sep 17 00:00:00 2001 From: Nishi Date: Wed, 16 Sep 2026 03:29:42 +0900 Subject: [PATCH 112/168] add codeblock --- examples/basic/document.c | 1 + include/Mw/Constants.h | 1 + src/widget/document.c | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/examples/basic/document.c b/examples/basic/document.c index 9bce548..1051a6b 100644 --- a/examples/basic/document.c +++ b/examples/basic/document.c @@ -35,6 +35,7 @@ int main() { int i; strcpy(text, "# Hello world!\nThis is a __test__ text...\n\n`Some monospace here`\n\n~~Removed~~"); + strcat(text, "\n```\nint main(){\n printf(\"Hello, world!\\n\");\n}\n```"); for(i = 0; i < 10; i++) { strcat(text, "\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); } diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index ed77ab5..0a79ae6 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -124,6 +124,7 @@ enum MwCHART { enum MwDOCUMENT_LAYOUT { MwDOCUMENT_TEXT = 0, MwDOCUMENT_NEWLINE, + MwDOCUMENT_SPACE, MwDOCUMENT_HEADER, MwDOCUMENT_BOLD, MwDOCUMENT_MONOSPACE, diff --git a/src/widget/document.c b/src/widget/document.c index 3f83646..2dc7ec9 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -156,6 +156,14 @@ static int enter_block(MD_BLOCKTYPE type, void* detail, void* userdata) { arrput(d->layouts, l); break; } + case MD_BLOCK_CODE: + { + l.type = MwDOCUMENT_MONOSPACE; + l.integer = 1; + + arrput(d->layouts, l); + break; + } default: break; } @@ -187,6 +195,14 @@ static int leave_block(MD_BLOCKTYPE type, void* detail, void* userdata) { arrput(d->layouts, l); break; } + case MD_BLOCK_CODE: + { + l.type = MwDOCUMENT_MONOSPACE; + l.integer = 0; + + arrput(d->layouts, l); + break; + } default: break; } @@ -311,12 +327,24 @@ static int text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userd next = strchr(str, ' '); if(next != NULL) next[0] = 0; - if(strlen(str) > 0) { + if(strcmp(str, "\n") == 0) { + memset(&l, 0, sizeof(l)); + + l.type = MwDOCUMENT_NEWLINE; + + arrput(d->layouts, l); + } else if(strlen(str) > 0) { memset(&l, 0, sizeof(l)); l.type = MwDOCUMENT_TEXT; l.text = MwStringDuplicate(str); + arrput(d->layouts, l); + } else { + memset(&l, 0, sizeof(l)); + + l.type = MwDOCUMENT_SPACE; + arrput(d->layouts, l); } @@ -374,6 +402,11 @@ static void layout(MwWidget handle) { x += t; break; } + case MwDOCUMENT_SPACE: + { + x += MwTextWidth(handle, TOPFONT, " "); + break; + } case MwDOCUMENT_NEWLINE: { x = 0; From 8d48075f50780c03715c56e65616da4006e484e3 Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 17 Sep 2026 02:03:09 +0900 Subject: [PATCH 113/168] MwNdocumentActivateHandler --- examples/basic/document.c | 18 +++- include/Mw/Constants.h | 1 + include/Mw/Resource/Cursor.h | 20 ++++ include/Mw/StringDefs.h | 1 + include/Mw/TypeDefs.h | 13 ++- milsko.xml | 4 + src/cursor/center.c | 43 ++++++++ src/cursor/hand.c | 46 ++++++++ src/widget/document.c | 202 +++++++++++++++++++++++++++++++---- 9 files changed, 322 insertions(+), 26 deletions(-) create mode 100644 src/cursor/center.c create mode 100644 src/cursor/hand.c diff --git a/examples/basic/document.c b/examples/basic/document.c index 1051a6b..f9529fe 100644 --- a/examples/basic/document.c +++ b/examples/basic/document.c @@ -30,14 +30,25 @@ static void MWAPI layout_document(MwWidget handle, void* user, void* call) { NULL); } +static void MWAPI activate_document(MwWidget handle, void* user, void* call) { + if(strcmp((const char*)call, "you_clicked") == 0) { + MwVaApply(document, + MwNtext, "# You clicked the thing!", + NULL); + } +} + int main() { char* text = malloc(64 * 1024); int i; - strcpy(text, "# Hello world!\nThis is a __test__ text...\n\n`Some monospace here`\n\n~~Removed~~"); - strcat(text, "\n```\nint main(){\n printf(\"Hello, world!\\n\");\n}\n```"); + strcpy(text, "# Hello world!\nThis is a __test__ text...\n\n"); + strcat(text, "`Some monospace here`\n\n"); + strcat(text, "~~Removed~~\n"); + strcat(text, "```\nint main(){\n printf(\"Hello, world!\\n\");\n}\n```\n"); + strcat(text, "[Click me!](you_clicked)\n\n"); for(i = 0; i < 10; i++) { - strcat(text, "\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); + strcat(text, "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n"); } MwLibraryInit(); @@ -54,6 +65,7 @@ int main() { MwAddUserHandler(window, MwNresizeHandler, resize_window, NULL); MwAddUserHandler(document, MwNlayoutHandler, layout_document, NULL); + MwAddUserHandler(document, MwNdocumentActivateHandler, activate_document, NULL); resize_window(window, NULL, NULL); diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index 0a79ae6..a0eec8b 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -130,6 +130,7 @@ enum MwDOCUMENT_LAYOUT { MwDOCUMENT_MONOSPACE, MwDOCUMENT_STRIKETHROUGH, MwDOCUMENT_UNDERLINE, + MwDOCUMENT_CLICKABLE }; enum MwMOUSE { diff --git a/include/Mw/Resource/Cursor.h b/include/Mw/Resource/Cursor.h index 9a47802..c9347b9 100644 --- a/include/Mw/Resource/Cursor.h +++ b/include/Mw/Resource/Cursor.h @@ -63,6 +63,26 @@ MWDECL MwCursor MwCursorHidden; */ MWDECL MwCursor MwCursorHiddenMask; +/*! + * @brief Hand cursor + */ +MWDECL MwCursor MwCursorHand; + +/*! + * @brief Hand cursor mask + */ +MWDECL MwCursor MwCursorHandMask; + +/*! + * @brief Center cursor + */ +MWDECL MwCursor MwCursorCenter; + +/*! + * @brief Center cursor mask + */ +MWDECL MwCursor MwCursorCenterMask; + #ifdef __cplusplus } #endif diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index b3f527b..cf0a723 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -84,6 +84,7 @@ #define MwNactivateHandler "Cactivate" #define MwNlistBoxActivateHandler "ClistBoxActivate" #define MwNtreeViewActivateHandler "CtreeViewActivate" +#define MwNdocumentActivateHandler "CdocumentActivate" #define MwNresizeHandler "Cresize" #define MwNtickHandler "Ctick" #define MwNmenuHandler "Cmenu" diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 2a11d36..3463b37 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -33,6 +33,7 @@ typedef struct _MwTable* MwTable; typedef struct _MwChartEntry MwChartEntry; typedef struct _MwChart* MwChart; typedef struct _MwDocumentLayout MwDocumentLayout; +typedef struct _MwDocumentClickable MwDocumentClickable; typedef struct _MwDocument* MwDocument; typedef struct _MwMouse MwMouse; typedef struct _MwTTFInfo* MwTTFInfo; @@ -278,9 +279,17 @@ struct _MwDocumentLayout { MwFLFont font; }; +struct _MwDocumentClickable { + MwRect hitbox; + char* event; +}; + struct _MwDocument { - MwDocumentLayout* layouts; - MwFLFont headers[6]; + MwDocumentLayout* layouts; + MwDocumentClickable* clickables; + MwFLFont headers[6]; + + int center_cursor; }; struct _MwTTFInfo { diff --git a/milsko.xml b/milsko.xml index 1bb19fd..5b90410 100644 --- a/milsko.xml +++ b/milsko.xml @@ -154,6 +154,9 @@ + + + @@ -710,6 +713,7 @@ +
    diff --git a/src/cursor/center.c b/src/cursor/center.c new file mode 100644 index 0000000..2340f57 --- /dev/null +++ b/src/cursor/center.c @@ -0,0 +1,43 @@ +#include + +/** + * Created by bitmaptobdf + * + * Copyright notice: + * These ""glyphs"" are unencumbered + */ +MwCursor MwCursorCenter = { + 10, 14, -4, -14, {48, /* ....##.... */ + 48, /* ....##.... */ + 120, /* ...####... */ + 120, /* ...####... */ + 252, /* ..######.. */ + 252, /* ..######.. */ + 510, /* .########. */ + 510, /* .########. */ + 819, /* ##..##..## */ + 561, /* #...##...# */ + 48, /* ....##.... */ + 48, /* ....##.... */ + 48, /* ....##.... */ + 48, /* ....##.... */ + 0, 0}}; +MwCursor MwCursorCenterMask = { + 12, 16, -5, -15, { + 240, /* ....####.... */ + 240, /* ....####.... */ + 504, /* ...######... */ + 504, /* ...######... */ + 1020, /* ..########.. */ + 1020, /* ..########.. */ + 2046, /* .##########. */ + 2046, /* .##########. */ + 4095, /* ############ */ + 4095, /* ############ */ + 4095, /* ############ */ + 3831, /* ###.####.### */ + 240, /* ....####.... */ + 240, /* ....####.... */ + 240, /* ....####.... */ + 240 /* ....####.... */ + }}; diff --git a/src/cursor/hand.c b/src/cursor/hand.c new file mode 100644 index 0000000..07b015d --- /dev/null +++ b/src/cursor/hand.c @@ -0,0 +1,46 @@ +#include + +/** + * Created by bitmaptobdf + * + * Copyright notice: + * These ""glyphs"" are unencumbered + */ +MwCursor MwCursorHand = { + 13, 16, -12, -16, { + 3, /* ...........## */ + 15, /* .........#### */ + 60, /* .......####.. */ + 120, /* ......####... */ + 240, /* .....####.... */ + 504, /* ....######... */ + 1020, /* ...########.. */ + 3064, /* .#.#######... */ + 8188, /* ###########.. */ + 6140, /* #.#########.. */ + 504, /* ....######... */ + 496, /* ....#####.... */ + 4736, /* #..#.#....... */ + 6272, /* ##...#....... */ + 3328, /* .##.#........ */ + 1536 /* ..##......... */ + }}; +MwCursor MwCursorHandMask = { + 13, 16, -12, -16, { + 7, /* ..........### */ + 31, /* ........##### */ + 126, /* ......######. */ + 252, /* .....######.. */ + 504, /* ....######... */ + 1020, /* ...########.. */ + 4094, /* .###########. */ + 8190, /* ############. */ + 8190, /* ############. */ + 8190, /* ############. */ + 8188, /* ###########.. */ + 8184, /* ##########... */ + 8176, /* #########.... */ + 8128, /* #######...... */ + 8064, /* ######....... */ + 3840 /* .####........ */ + }}; diff --git a/src/widget/document.c b/src/widget/document.c index 2dc7ec9..7611c62 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -3,7 +3,7 @@ #include "../../external/md4c.h" #include "../../external/stb_ds.h" -#define IsFontChange(x) ((x) == MwDOCUMENT_HEADER || (x) == MwDOCUMENT_BOLD || (x) == MwDOCUMENT_MONOSPACE || (x) == MwDOCUMENT_STRIKETHROUGH) +#define IsFontChange(x) ((x) == MwDOCUMENT_HEADER || (x) == MwDOCUMENT_BOLD || (x) == MwDOCUMENT_MONOSPACE) static void reset(MwWidget handle) { MwDocument d = handle->internal; @@ -13,6 +13,11 @@ static void reset(MwWidget handle) { if(d->layouts[i].text != NULL) free(d->layouts[i].text); } arrfree(d->layouts); + + for(i = 0; i < arrlen(d->clickables); i++) { + if(d->clickables[i].event != NULL) free(d->clickables[i].event); + } + arrfree(d->clickables); } static int wcreate(MwWidget handle) { @@ -52,11 +57,11 @@ static void draw(MwWidget handle) { MwRect r; int i; MwFLFont font = NULL; - MwPoint u_p, s_p; - int u = 0, s = 0; + MwPoint u_p, s_p, c_p; + int u = 0, s = 0, c = 0; - u_p.x = u_p.y = 0; - s_p.x = s_p.y = 0; + u_p.x = s_p.x = c_p.x = 0; + u_p.y = s_p.y = c_p.y = 0; r.x = 0; r.y = 0; @@ -75,9 +80,7 @@ static void draw(MwWidget handle) { p.x = l->x; p.y = l->y + MwTextHeight(handle, font, l->text) / 2; - MwDrawText(handle, font, &p, l->text, MwALIGNMENT_BEGINNING, text); - - if(u || s) { + if(u || s || c) { MwPoint line[2]; int j; @@ -85,31 +88,74 @@ static void draw(MwWidget handle) { u_p.x = 0; u_p.y = l->y; } + if(s_p.y != l->y) { + s_p.x = 0; + s_p.y = l->y; + } + if(c_p.y != l->y) { + c_p.x = 0; + c_p.y = l->y; + } - line[0] = u_p; - line[1] = u_p; + for(j = 0; j < 3; j++) { + if(j == 0) { + if(!u) continue; + line[0] = u_p; + line[1] = u_p; + } else if(j == 1) { + if(!s) continue; + line[0] = s_p; + line[1] = s_p; + } else if(j == 2) { + if(!c) continue; + line[0] = c_p; + line[1] = c_p; + } - line[1].x = p.x + MwTextWidth(handle, font, l->text); - u_p.x = line[1].x; + line[1].x = p.x + MwTextWidth(handle, font, l->text); - for(j = 0; j < 2; j++) { - line[0].y += MwTextHeight(handle, font, l->text) / 2; - line[1].y += MwTextHeight(handle, font, l->text) / 2; - if((j == 0 && s) || (j == 1 && u)) MwLLLine(handle->lowlevel, line, text); + if(j == 0) u_p.x = line[1].x; + if(j == 1) s_p.x = line[1].x; + if(j == 2) c_p.x = line[1].x; + + if(j == 2) { + MwRect c_r; + + c_r.x = line[0].x; + c_r.y = line[0].y; + c_r.width = line[1].x - line[0].x; + c_r.height = MwTextHeight(handle, font, l->text); + + MwDrawRect(handle, &c_r, text); + } + + if(j == 0 || j == 1) { + line[0].y += MwTextHeight(handle, font, l->text) / 2 * (2 - j); + line[1].y += MwTextHeight(handle, font, l->text) / 2 * (2 - j); + MwLLLine(handle->lowlevel, line, c ? base : text); + } } } + + handle->bgcolor = c ? text : NULL; + MwDrawText(handle, font, &p, l->text, MwALIGNMENT_BEGINNING, c ? base : text); + handle->bgcolor = NULL; break; } case MwDOCUMENT_UNDERLINE: case MwDOCUMENT_STRIKETHROUGH: + case MwDOCUMENT_CLICKABLE: { if(l->type == MwDOCUMENT_UNDERLINE) { u = l->integer; - } else { + } else if(l->type == MwDOCUMENT_STRIKETHROUGH) { s = l->integer; + } else { + c = l->integer; } - if(l->type == MwDOCUMENT_UNDERLINE ? u : s) { + if(l->type == MwDOCUMENT_UNDERLINE ? u : l->type == MwDOCUMENT_STRIKETHROUGH ? s + : c) { int j; for(j = i + 1; j < arrlen(d->layouts) && d->layouts[j].type != l->type; j++) { @@ -121,8 +167,10 @@ static void draw(MwWidget handle) { if(l->type == MwDOCUMENT_UNDERLINE) { u_p = p; - } else { + } else if(l->type == MwDOCUMENT_STRIKETHROUGH) { s_p = p; + } else { + c_p = p; } break; } @@ -141,6 +189,29 @@ static void draw(MwWidget handle) { MwLLFreeColor(base); } +static char* in_hitbox(MwWidget handle, MwPoint* p) { + int i; + MwDocument d = handle->internal; + + for(i = 0; i < arrlen(d->clickables); i++) { + MwRect hitbox = d->clickables[i].hitbox; + + if(hitbox.x <= p->x && p->x <= (hitbox.x + hitbox.width) && hitbox.y <= p->y && p->y <= (hitbox.y + hitbox.height)) { + return d->clickables[i].event; + } + } + + return NULL; +} + +static void click(MwWidget handle) { + char* event; + + if((event = in_hitbox(handle, &handle->mouse_point)) != NULL) { + MwDispatchUserHandler(handle, MwNdocumentActivateHandler, event); + } +} + static int enter_block(MD_BLOCKTYPE type, void* detail, void* userdata) { MwDocument d = userdata; MwDocumentLayout l; @@ -251,6 +322,21 @@ static int enter_span(MD_SPANTYPE type, void* detail, void* userdata) { arrput(d->layouts, l); break; } + case MD_SPAN_A: + { + MD_ATTRIBUTE* href = &((MD_SPAN_A_DETAIL*)detail)->href; + char* text = malloc(href->size + 1); + + memcpy(text, href->text, href->size); + text[href->size] = 0; + + l.type = MwDOCUMENT_CLICKABLE; + l.text = text; + l.integer = 1; + + arrput(d->layouts, l); + break; + } default: break; } @@ -299,6 +385,14 @@ static int leave_span(MD_SPANTYPE type, void* detail, void* userdata) { arrput(d->layouts, l); break; } + case MD_SPAN_A: + { + l.type = MwDOCUMENT_CLICKABLE; + l.integer = 0; + + arrput(d->layouts, l); + break; + } default: break; } @@ -371,6 +465,15 @@ static int text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userd #define TOPFONT fontstack[arrlen(fontstack) - 1] #define POP arrdel(fontstack, arrlen(fontstack) - 1); +static void add_clickable(MwDocument d, char* c_title, MwRect* clickable) { + MwDocumentClickable c; + + c.hitbox = *clickable; + c.event = MwStringDuplicate(c_title); + + arrput(d->clickables, c); +} + static void layout(MwWidget handle) { MwDocument d = handle->internal; int w = MwGetInteger(handle, MwNwidth); @@ -378,9 +481,16 @@ static void layout(MwWidget handle) { int x = 0; int y = 0; MwFLFont* fontstack = NULL; + MwRect clickable; + char* c_title = NULL; arrput(fontstack, NULL); + for(i = 0; i < arrlen(d->clickables); i++) { + if(d->clickables[i].event != NULL) free(d->clickables[i].event); + } + arrfree(d->clickables); + for(i = 0; i < arrlen(d->layouts); i++) { MwDocumentLayout* l = &d->layouts[i]; @@ -399,7 +509,21 @@ static void layout(MwWidget handle) { l->x = x; l->y = y; + if(c_title != NULL) { + if(clickable.y < y) { + if(clickable.y >= 0 && clickable.width > 0) add_clickable(d, c_title, &clickable); + + clickable.x = x; + clickable.y = y; + } + } + x += t; + + if(c_title != NULL) { + clickable.width = x - clickable.x; + } + break; } case MwDOCUMENT_SPACE: @@ -411,6 +535,11 @@ static void layout(MwWidget handle) { { x = 0; y += MwTextHeight(handle, TOPFONT, "M"); + + if(c_title != NULL) { + add_clickable(d, c_title, &clickable); + } + break; } case MwDOCUMENT_BOLD: @@ -447,6 +576,22 @@ static void layout(MwWidget handle) { } break; } + case MwDOCUMENT_CLICKABLE: + { + if(l->integer) { + clickable.y = -100; + clickable.width = 0; + clickable.height = MwTextHeight(handle, TOPFONT, "M"); + + c_title = MwStringDuplicate(l->text); + } else { + if(clickable.y >= 0 && clickable.width > 0) add_clickable(d, c_title, &clickable); + + free(c_title); + c_title = NULL; + } + break; + } } l->font = TOPFONT; @@ -484,6 +629,21 @@ static void prop_change(MwWidget handle, const char* key) { } } +static void mouse_move(MwWidget handle) { + char* event = in_hitbox(handle, &handle->mouse_point); + MwDocument d = handle->internal; + + if(d->center_cursor && event == NULL) { + MwLLSetCursor(handle->lowlevel, &MwCursorDefault, &MwCursorDefaultMask); + + d->center_cursor = 0; + } else if(!d->center_cursor && event != NULL) { + MwLLSetCursor(handle->lowlevel, &MwCursorCenter, &MwCursorCenterMask); + + d->center_cursor = 1; + } +} + static void resize(MwWidget handle) { layout(handle); } @@ -492,10 +652,10 @@ MwClassRec MwDocumentClassRec = { wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ - NULL, /* click */ + click, /* click */ NULL, /* parent_resize */ prop_change, /* prop_change */ - NULL, /* mouse_move */ + mouse_move, /* mouse_move */ NULL, /* mouse_up */ NULL, /* mouse_down */ NULL, /* key */ From ae2d859e63fbc3d1c357034d9236e8124b7b29ec Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 17 Sep 2026 02:06:39 +0900 Subject: [PATCH 114/168] move --- src/widget/document.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/widget/document.c b/src/widget/document.c index 7611c62..55dd1f0 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -474,6 +474,21 @@ static void add_clickable(MwDocument d, char* c_title, MwRect* clickable) { arrput(d->clickables, c); } +static void mouse_move(MwWidget handle) { + char* event = in_hitbox(handle, &handle->mouse_point); + MwDocument d = handle->internal; + + if(d->center_cursor && event == NULL) { + MwLLSetCursor(handle->lowlevel, &MwCursorDefault, &MwCursorDefaultMask); + + d->center_cursor = 0; + } else if(!d->center_cursor && event != NULL) { + MwLLSetCursor(handle->lowlevel, &MwCursorCenter, &MwCursorCenterMask); + + d->center_cursor = 1; + } +} + static void layout(MwWidget handle) { MwDocument d = handle->internal; int w = MwGetInteger(handle, MwNwidth); @@ -602,6 +617,7 @@ static void layout(MwWidget handle) { arrfree(fontstack); + mouse_move(handle); MwForceRender(handle); } @@ -629,21 +645,6 @@ static void prop_change(MwWidget handle, const char* key) { } } -static void mouse_move(MwWidget handle) { - char* event = in_hitbox(handle, &handle->mouse_point); - MwDocument d = handle->internal; - - if(d->center_cursor && event == NULL) { - MwLLSetCursor(handle->lowlevel, &MwCursorDefault, &MwCursorDefaultMask); - - d->center_cursor = 0; - } else if(!d->center_cursor && event != NULL) { - MwLLSetCursor(handle->lowlevel, &MwCursorCenter, &MwCursorCenterMask); - - d->center_cursor = 1; - } -} - static void resize(MwWidget handle) { layout(handle); } From d0c79575059d23cb9966a1b742fcd10b3a2e173f Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 17 Sep 2026 02:07:06 +0900 Subject: [PATCH 115/168] update --- NTMakefile | 6 ++++-- WatMakefile | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/NTMakefile b/NTMakefile index 213800d..b07f798 100644 --- a/NTMakefile +++ b/NTMakefile @@ -37,8 +37,10 @@ clean: del /f /q src\color.obj del /f /q src\core.obj del /f /q src\cursor\arrow.obj + del /f /q src\cursor\center.obj del /f /q src\cursor\cross.obj del /f /q src\cursor\default.obj + del /f /q src\cursor\hand.obj del /f /q src\cursor\hidden.obj del /f /q src\cursor\text.obj del /f /q src\default.obj @@ -340,8 +342,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index 0b846d1..fd98079 100644 --- a/WatMakefile +++ b/WatMakefile @@ -36,8 +36,10 @@ clean: .SYMBOLIC %erase src/color.obj %erase src/core.obj %erase src/cursor/arrow.obj + %erase src/cursor/center.obj %erase src/cursor/cross.obj %erase src/cursor/default.obj + %erase src/cursor/hand.obj %erase src/cursor/hidden.obj %erase src/cursor/text.obj %erase src/default.obj @@ -339,8 +341,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -398,10 +400,14 @@ src/core.obj: src/core.c $(CC) $(MW_CFLAGS) -fo=$@ src/core.c src/cursor/arrow.obj: src/cursor/arrow.c $(CC) $(MW_CFLAGS) -fo=$@ src/cursor/arrow.c +src/cursor/center.obj: src/cursor/center.c + $(CC) $(MW_CFLAGS) -fo=$@ src/cursor/center.c src/cursor/cross.obj: src/cursor/cross.c $(CC) $(MW_CFLAGS) -fo=$@ src/cursor/cross.c src/cursor/default.obj: src/cursor/default.c $(CC) $(MW_CFLAGS) -fo=$@ src/cursor/default.c +src/cursor/hand.obj: src/cursor/hand.c + $(CC) $(MW_CFLAGS) -fo=$@ src/cursor/hand.c src/cursor/hidden.obj: src/cursor/hidden.c $(CC) $(MW_CFLAGS) -fo=$@ src/cursor/hidden.c src/cursor/text.obj: src/cursor/text.c From de5e26b1282971b1631a7a6f3722056a9a48a4cf Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 17 Sep 2026 03:21:27 +0900 Subject: [PATCH 116/168] fix --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 534614f..07f7bb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -497,7 +497,7 @@ configure_file( install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc - DESTINATION $ENV{MINGW_PREFIX}/${CMAKE_INSTALL_DATADIR}/pkgconfig + DESTINATION $ENV{MINGW_PREFIX}/${CMAKE_INSTALL_FULL_DATADIR}/pkgconfig ) if(MW_INSTALL_HEADERS) From 74054fba4b1590758d8afde29d0beff9742fd1e3 Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 17 Sep 2026 03:36:00 +0900 Subject: [PATCH 117/168] fix --- src/draw.c | 3 +++ src/widget/document.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/draw.c b/src/draw.c index eb15c76..be82fb4 100644 --- a/src/draw.c +++ b/src/draw.c @@ -138,6 +138,9 @@ void MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color) { MwFixRect(&r); + r.width--; + r.height--; + p[0].x = r.x; p[0].y = r.y; diff --git a/src/widget/document.c b/src/widget/document.c index 55dd1f0..1f48cec 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -514,7 +514,7 @@ static void layout(MwWidget handle) { { int t = MwTextWidth(handle, TOPFONT, l->text); - if(x > 0) x += MwTextWidth(handle, TOPFONT, " "); + if(x > 0) x += MwTextWidth(handle, TOPFONT, "."); if((x + t) >= w) { x = 0; @@ -543,7 +543,7 @@ static void layout(MwWidget handle) { } case MwDOCUMENT_SPACE: { - x += MwTextWidth(handle, TOPFONT, " "); + x += MwTextWidth(handle, TOPFONT, "."); break; } case MwDOCUMENT_NEWLINE: From 7398604b7ca6bb56d4129b02448e40a488182d02 Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 17 Sep 2026 03:38:11 +0900 Subject: [PATCH 118/168] unfix --- src/draw.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/draw.c b/src/draw.c index be82fb4..eb15c76 100644 --- a/src/draw.c +++ b/src/draw.c @@ -138,9 +138,6 @@ void MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color) { MwFixRect(&r); - r.width--; - r.height--; - p[0].x = r.x; p[0].y = r.y; From f9bbba8af9506952ed9317e1bdfea95babf0864a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 16 Sep 2026 12:48:51 -0700 Subject: [PATCH 119/168] minor improvements on wayland --- .gitignore | 2 ++ include/Mw/LowLevel/Wayland.h | 13 ------------- src/backend/wayland/buffer.c | 13 +++++++++++++ src/backend/wayland/wayland.c | 33 +++++++-------------------------- 4 files changed, 22 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index 58b172a..3faccd3 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ compile_flags.txt *.finf *.gdb +flamegraph.svg +perf.* diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 7a2c25c..3b79184 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -426,13 +426,9 @@ struct _MwLLWayland { MwBool force_render; MwBool did_event_loop_early; - MwBool do_cascading_draw; - int cascading_child_num; MwBool dispatching_resize; - MwBool is_toplevel_menu; - struct _MwLLWaylandShmBuffer framebuffer; struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; @@ -440,15 +436,6 @@ struct _MwLLWayland { MwLLPixmap icon_pixmap; - pthread_mutex_t eventsMutex; - - int cancelEvent; - int numCallbacksRunning; - - uint32_t last_time; - - MwBool moving; - MwI64 keyboard_rate; MwI32 keyboard_delay; int last_pressed_key; diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index cb1eca5..48071ec 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -113,3 +113,16 @@ void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer) { close(buffer->fd_back); buffer->setup = MwFALSE; } + +void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { + if(self->wayland.configured) { + memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); + if(buffer->surface) { + // Yes this is needed every time, it's how we fix weston. + if(self->wayland.configured) + wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); + + wl_surface_commit(buffer->surface); + } + } +} diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index bd17f84..9d8d634 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -218,19 +218,6 @@ static void xdg_surface_configure( self->wayland.configured = MwTRUE; } -void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { - if(self->wayland.configured) { - memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); - if(buffer->surface) { - // Yes this is needed every time, it's how we fix weston. - if(self->wayland.configured) - wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - - wl_surface_commit(buffer->surface); - } - } -} - /* Toplevel setup function */ static void setup_toplevel(MwLL r, int x, int y) { char* mw_force_csd = getenv("MW_FORCE_CSD"); @@ -986,7 +973,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); memset(r, 0, sizeof(*r)); - pthread_mutex_init(&r->wayland.eventsMutex, NULL); + // pthread_mutex_init(&r->wayland.eventsMutex, NULL); MwLLCreateCommon(r); r->wayland.is_toplevel = parent == NULL; @@ -1015,8 +1002,6 @@ static void MwLLDestroyImpl(MwLL handle) { MwLLWaylandFlush(handle); - handle->wayland.cancelEvent = MwTRUE; - MwLLDestroyCommon(handle); tv.tv_sec = 0; @@ -1050,7 +1035,7 @@ static void MwLLDestroyImpl(MwLL handle) { printf("widget invalid\n"); } - pthread_mutex_destroy(&handle->wayland.eventsMutex); + // pthread_mutex_destroy(&handle->wayland.eventsMutex); free(handle); } @@ -1321,10 +1306,6 @@ static void MwLLEndDrawImpl(MwLL handle) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); - - if(handle->wayland.type != MwLL_WAYLAND_SUBLEVEL) { - handle->wayland.do_cascading_draw = 1; - } } } @@ -1382,16 +1363,16 @@ static int MwLLPendingImpl(MwLL handle) { handle->wayland.resizing = 0; + if(handle->wayland.type != MwLL_WAYLAND_SUBLEVEL) { + draw_children(handle); + frontbuffer_draw(handle); + } + if(handle->wayland.setting_wh) { actually_set_wh(handle); handle->wayland.setting_wh = 0; } - if(handle->wayland.do_cascading_draw) { - draw_children(handle); - frontbuffer_draw(handle); - } - handle->wayland.end_time = MwTimeGetTick(); if(handle->wayland.holding_key) { From 1dda7934ce9665657c6b7235171b3422ca875358 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 07:25:52 +0900 Subject: [PATCH 120/168] wayland flickering/ghosting fix --- CMakeLists.txt | 1 + include/Mw/LowLevel/Cairo.h | 3 ++ include/Mw/LowLevel/Wayland.h | 6 ++++ pl/rules.pl | 1 + src/backend/cairo.c | 27 ++++++++------ src/backend/wayland/buffer.c | 11 ++++-- src/backend/wayland/interfaces.c | 17 +++++++++ src/backend/wayland/wayland.c | 62 +++++++++++++++----------------- 8 files changed, 82 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07f7bb9..f5bb780 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,7 @@ if(MW_USE_WAYLAND) scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1") + scan_wayland_protocol("staging" "fifo" "-v1") scan_wayland_protocol_from_file("wlr-layer-shell" "wlr-layer-shell-unstable-v1.xml") target_sources( diff --git a/include/Mw/LowLevel/Cairo.h b/include/Mw/LowLevel/Cairo.h index 680c651..92304fa 100644 --- a/include/Mw/LowLevel/Cairo.h +++ b/include/Mw/LowLevel/Cairo.h @@ -196,6 +196,9 @@ struct _MwLLCairo { /* The cairo to actually use for draw operations. Typically is front_cairo, but wayland's MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */ cairo_t* selected_cairo; + cairo_surface_t* frontbuffer_cs; + cairo_t* frontbuffer_cairo; + int x; int y; int width; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 3b79184..e3b9ff9 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -207,6 +207,7 @@ MwInline int wayland_load_funcs() { #include "Wayland/relative-pointer-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h" #include "Wayland/wlr-layer-shell-client-protocol.h" +#include "Wayland/fifo-client-protocol.h" #endif typedef struct wayland_protocol { @@ -265,6 +266,7 @@ struct _MwLLWaylandShmBuffer { struct wl_buffer* shm_buffer_back; struct wl_surface* surface; struct wl_output* output; + struct wp_fifo_v1* fifo; MwU8* buf; MwU8* buf_back; @@ -426,9 +428,13 @@ struct _MwLLWayland { MwBool force_render; MwBool did_event_loop_early; + MwBool do_cascading_draw; + int cascading_child_num; MwBool dispatching_resize; + MwBool is_toplevel_menu; + struct _MwLLWaylandShmBuffer framebuffer; struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; diff --git a/pl/rules.pl b/pl/rules.pl index 551d391..f12c092 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -66,6 +66,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); + scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 3683ca8..9dab1c1 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -113,13 +113,16 @@ void MwLLCairoDrawPixmap(struct _MwLLCairo handle, MwRect* rect, MwLLPixmap pixm void MwLLCairoFrontSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) { if(data) { - cairo->front_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4); + cairo->front_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4); + cairo->frontbuffer_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4); } else { - cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo->frontbuffer_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); } - cairo->front_cs_back = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - cairo->front_cairo_back = cairo_create(cairo->front_cs_back); - cairo->front_cairo = cairo_create(cairo->front_cs); + cairo->front_cs_back = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo->front_cairo_back = cairo_create(cairo->front_cs_back); + cairo->front_cairo = cairo_create(cairo->front_cs); + cairo->frontbuffer_cairo = cairo_create(cairo->frontbuffer_cs); } void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) { @@ -135,6 +138,8 @@ void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) { cairo_destroy(cairo->front_cairo); cairo_destroy(cairo->front_cairo_back); cairo_surface_destroy(cairo->front_cs); + cairo_surface_destroy(cairo->frontbuffer_cs); + cairo_destroy(cairo->frontbuffer_cairo); }; void MwLLCairoBackDestroy(struct _MwLLCairo* cairo) { cairo_destroy(cairo->back_cairo); @@ -214,8 +219,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -259,10 +264,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index 48071ec..79ce72c 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -10,6 +10,9 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size); if(wayland->configured) wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); + if(wayland->framebuffer.fifo) + wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); + wl_surface_commit(wayland->framebuffer.surface); MwLLWaylandHangUntilConfigured((MwLL)wayland); @@ -38,6 +41,8 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) { memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size); if(wayland->configured) wl_surface_attach(wayland->backbuffer.surface, wayland->backbuffer.shm_buffer, 0, 0); + // if(wayland->framebuffer.fifo) + // wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); wl_surface_commit(wayland->backbuffer.surface); MwLLWaylandHangUntilConfigured((MwLL)wayland); MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->backbuffer); @@ -119,9 +124,11 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); if(buffer->surface) { // Yes this is needed every time, it's how we fix weston. - if(self->wayland.configured) + if(self->wayland.configured) { wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - + } + if(buffer->fifo) + wp_fifo_v1_wait_barrier(buffer->fifo); wl_surface_commit(buffer->surface); } } diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index dd58f9a..3378d0d 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -749,6 +749,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time if(self->wayland.backbuffer.surface) { wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); } + WAYLAND_EVENT_OP_END(self); }; @@ -1511,6 +1512,21 @@ static void zwlr_layer_shell_v1_interface_destroy(struct _MwLLWayland* wayland, free(data); } +static wayland_protocol_t* wp_fifo_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + + proto->context = wl_registry_bind(wayland->registry, name, &wp_fifo_manager_v1_interface, version); + proto->listener = NULL; + + return proto; +} + +static void wp_fifo_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + (void)wayland; + + free(data); +} + /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { /* Convience macro for adding the interface functions to the setup map */ @@ -1553,6 +1569,7 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(xdg_toplevel_icon_manager_v1); WL_INTERFACE(wl_subcompositor); WL_INTERFACE(wl_seat); + WL_INTERFACE(wp_fifo_manager_v1); } else if(wayland->type == MwLL_WAYLAND_POPUP) { WL_INTERFACE(wl_seat); } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 9d8d634..ff8fb49 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -265,6 +265,10 @@ static void setup_toplevel(MwLL r, int x, int y) { r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); wl_subsurface_set_desync(r->wayland.toplevel->ssurface); + if(WAYLAND_GET_INTERFACE(r->wayland, wp_fifo_manager_v1) != NULL) { + r->wayland.framebuffer.fifo = wp_fifo_manager_v1_get_fifo(WAYLAND_GET_INTERFACE(r->wayland, wp_fifo_manager_v1)->context, r->wayland.framebuffer.surface); + } + r->wayland.toplevel->xdg_surface = xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.backbuffer.surface); r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface); @@ -407,10 +411,13 @@ static void popup_configure(void* data, if(width < 50) width = 50; if(height < 50) height = 50; - self->wayland.x = x; - self->wayland.y = y; - self->wayland.ww = width; - self->wayland.wh = height; + self->wayland.x = x; + self->wayland.y = y; + + if(!self->wayland.setting_wh) { + self->wayland.ww = width; + self->wayland.wh = height; + } }; static void popup_done(void* data, @@ -439,10 +446,11 @@ struct xdg_popup_listener popup_listener = { static void setup_popup(MwLL r, int x, int y, MwLL parent) { char* mw_force_csd = getenv("MW_FORCE_CSD"); MwLL topmost_parent = r->wayland.parent; - r->wayland.type = MwLL_WAYLAND_POPUP; - r->wayland.x = x; - r->wayland.y = y; - r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); + + r->wayland.type = MwLL_WAYLAND_POPUP; + r->wayland.x = x; + r->wayland.y = y; + r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); if(parent) { MwWidget p = parent->common.user; @@ -908,13 +916,8 @@ static void draw_child(MwLL handle, MwLL child) { cairo_t* c; cairo_surface_t* cs; cairo_t* selected_cairo; - MwLL topmost_parent = handle; - if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP) { - while(topmost_parent->wayland.parent) { - topmost_parent = topmost_parent->wayland.parent; - } - } + draw_children(child); wl_surface_commit(child->wayland.framebuffer.surface); @@ -928,20 +931,18 @@ static void draw_child(MwLL handle, MwLL child) { cairo_paint(c); - // printf("%d %d\n", child->wayland.x, child->wayland.y); - cairo_set_source_surface(handle->wayland.cairo.front_cairo_back, cs, child->wayland.x, child->wayland.y); cairo_paint(handle->wayland.cairo.front_cairo_back); cairo_destroy(c); cairo_surface_destroy(cs); - - draw_children(child); } static void draw_children(MwLL handle) { wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + cairo_reset_clip(handle->wayland.cairo.front_cairo_back); + MwLLWaylandChildrenIterate(handle, draw_child); if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); @@ -949,24 +950,13 @@ static void draw_children(MwLL handle) { } static void frontbuffer_draw(MwLL handle) { - cairo_t* c; - cairo_surface_t* cs; - - cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, handle->wayland.ww, handle->wayland.wh); - c = cairo_create(cs); + cairo_t* c = handle->wayland.cairo.frontbuffer_cairo; cairo_set_source_surface(c, handle->wayland.cairo.front_cs_back, 0, 0); cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); - cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_OVER); cairo_paint(c); - - cairo_set_source_surface(handle->wayland.cairo.front_cairo, cs, 0, 0); - cairo_paint(handle->wayland.cairo.front_cairo); - - cairo_destroy(c); - cairo_surface_destroy(cs); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -1301,10 +1291,17 @@ static void MwLLBeginDrawImpl(MwLL handle) { } static void MwLLEndDrawImpl(MwLL handle) { + MwLL root = handle; + while(root->wayland.type == MwLL_WAYLAND_SUBLEVEL && root->wayland.parent) { + root = root->wayland.parent; + } + root->wayland.do_cascading_draw = MwTRUE; + if(handle->wayland.configured) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } + MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); } } @@ -1363,9 +1360,10 @@ static int MwLLPendingImpl(MwLL handle) { handle->wayland.resizing = 0; - if(handle->wayland.type != MwLL_WAYLAND_SUBLEVEL) { + if(handle->wayland.do_cascading_draw) { draw_children(handle); frontbuffer_draw(handle); + handle->wayland.do_cascading_draw = MwFALSE; } if(handle->wayland.setting_wh) { @@ -1430,7 +1428,6 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - if(!MwWaylandVulkan) { if(handle->wayland.did_event_loop_early) { handle->wayland.did_event_loop_early = MwFALSE; @@ -1450,7 +1447,6 @@ static void MwLLNextEventImpl(MwLL handle) { } static void MwLLSetTitleImpl(MwLL handle, const char* title) { - if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { xdg_toplevel_set_title(handle->wayland.toplevel->xdg_top_level, title); } From e81156708c8846f03d8100b231eb81784429daf2 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 16 Sep 2026 15:30:37 -0700 Subject: [PATCH 121/168] fix key repeat --- include/Mw/LowLevel/Wayland.h | 5 +++-- src/backend/wayland/interfaces.c | 6 +++--- src/backend/wayland/wayland.c | 6 +----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index e3b9ff9..5c91ebf 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -433,8 +433,6 @@ struct _MwLLWayland { MwBool dispatching_resize; - MwBool is_toplevel_menu; - struct _MwLLWaylandShmBuffer framebuffer; struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; @@ -491,6 +489,9 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_ /* Flush Wayland events */ void MwLLWaylandFlush(MwLL handle); +/* recursively dispatch the key event to focused widgets. */ +void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down); + /* Standard procedure before event callbacks in Wayland */ #define WAYLAND_EVENT_OP_START(self) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 3378d0d..5f4d6ff 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -1000,7 +1000,7 @@ static void keyboard_leave(void* data, WAYLAND_EVENT_OP_END(self); }; -static void key_dispatch(MwLL self, int* k, MwBool down) { +void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down) { if(self->common.user) { MwWidget w = self->common.user; int i, n; @@ -1019,7 +1019,7 @@ static void key_dispatch(MwLL self, int* k, MwBool down) { MwLLDispatch(child, key_released, k); } - key_dispatch(child, k, down); + MwLLRecursiveKeyDispatch(child, k, down); } } } @@ -1141,7 +1141,7 @@ static void keyboard_key(void* data, } else { self->wayland.holding_key = MwFALSE; } - key_dispatch(self, &key, state == WL_KEYBOARD_KEY_STATE_PRESSED); + MwLLRecursiveKeyDispatch(self, &key, state == WL_KEYBOARD_KEY_STATE_PRESSED); self->wayland.start_time = MwTimeGetTick(); self->wayland.next_elapsed = self->wayland.keyboard_delay; } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index ff8fb49..c854453 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1376,11 +1376,7 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->wayland.holding_key) { float elapsed = ((float)(handle->wayland.end_time - (float)handle->wayland.start_time)); if(elapsed >= handle->wayland.next_elapsed) { - MwLL topmost_parent = handle; - while(topmost_parent->wayland.parent) { - MwLLDispatch(topmost_parent, key, &handle->wayland.last_pressed_key); - topmost_parent = topmost_parent->wayland.parent; - } + MwLLRecursiveKeyDispatch(handle, &handle->wayland.last_pressed_key, MwTRUE); handle->wayland.next_elapsed = elapsed + handle->wayland.keyboard_rate; } } From e6e69b9915f366f422ffe802b44c671f42f03c97 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 16 Sep 2026 15:32:45 -0700 Subject: [PATCH 122/168] remove unused fields in MwLLWayland --- include/Mw/LowLevel/Wayland.h | 6 +----- src/backend/wayland/interfaces.c | 16 ---------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 5c91ebf..0d5a24f 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -320,7 +320,6 @@ struct _MwLLWayland { enum _MwLLWaylandType type_to_be; MwRect clipping_rect; - MwBool no; MwBool changing; MwBool detatching; @@ -361,8 +360,6 @@ struct _MwLLWayland { struct wl_region* region; struct wl_output* output; - struct wp_viewport* vp; - MwBool do_lock_pointer; struct zwp_pointer_constraints_v1* pointer_constraints; struct zwp_relative_pointer_manager_v1* relative_pointer_manager; @@ -378,9 +375,8 @@ struct _MwLLWayland { MwBool dark_theme_detection; MwU32 dark_theme; - /* clipboard related stuff. + /* clipboard/ related stuff. * Note that unlike most interfaces, we don't keep zwp_primary_selection stuff in a wayland_protocol_t because we use wl_data_device as a fallback and want to have it share memory space.*/ - struct { struct wl_data_device_manager* wl; struct zwp_primary_selection_device_manager_v1* zwp; diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 5f4d6ff..50a58e4 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -1431,20 +1431,6 @@ static void xdg_wm_base_interface_destroy(struct _MwLLWayland* wayland, wayland_ free(data); } -/* xdg_wm_base setup function */ -static wayland_protocol_t* wp_viewporter_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { - wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); - (void)version; - proto->context = wl_registry_bind(wayland->registry, name, &wp_viewporter_interface, 1); - - return proto; -} - -static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - (void)wayland; - (void)data; -} - /* zxdg_decoration_manager_v1 setup function */ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); @@ -1564,7 +1550,6 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(xdg_wm_base); WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { - WL_INTERFACE(wp_viewporter); WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); WL_INTERFACE(wl_subcompositor); @@ -1573,7 +1558,6 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { } else if(wayland->type == MwLL_WAYLAND_POPUP) { WL_INTERFACE(wl_seat); } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { - WL_INTERFACE(wp_viewporter); WL_INTERFACE(wl_subcompositor); WL_INTERFACE(wl_seat); } else { From f3c9c8650540317e459a1724fcc545ef35929be4 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 18:26:32 -0700 Subject: [PATCH 123/168] document bindings --- doc/BINDINGS.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 doc/BINDINGS.md diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md new file mode 100644 index 0000000..c5bcdd7 --- /dev/null +++ b/doc/BINDINGS.md @@ -0,0 +1,14 @@ +# Active Bindings + +| Language | Repo | Version | Notes | +| -------- | --------------------------------------------------------------------- | ------- | -------------- | +| Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | | +| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 1.5* | Auto-generated | +| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 1.5* | Auto-generated | +| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 1.5* | Auto-generated | + +# Inactive Bindings + +| Language | Repo | Version | Notes | +| -------- | ---------------------------------------------------- | ----------- | ----- | +| Rust | [milsko-rs](https://github.com/pyrite-dev/milsko-rs) | **pre-1.0** | | From a27d914ba2938eaac6137526146b23a02e2f9c30 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 18:28:08 -0700 Subject: [PATCH 124/168] in bindings document what aestrick means --- doc/BINDINGS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md index c5bcdd7..3782191 100644 --- a/doc/BINDINGS.md +++ b/doc/BINDINGS.md @@ -1,3 +1,5 @@ +\* = in-dev version + # Active Bindings | Language | Repo | Version | Notes | From 3e9ffcee0bc12aedb52e88a2c768a9466e01bb0f Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 18:31:09 -0700 Subject: [PATCH 125/168] node.js bindings are auto generated --- doc/BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md index 3782191..44014ac 100644 --- a/doc/BINDINGS.md +++ b/doc/BINDINGS.md @@ -4,7 +4,7 @@ | Language | Repo | Version | Notes | | -------- | --------------------------------------------------------------------- | ------- | -------------- | -| Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | | +| Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | Auto-generated | | C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 1.5* | Auto-generated | | Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 1.5* | Auto-generated | | Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 1.5* | Auto-generated | From 2b15e7e0a3a5aac4fff6af8ad7c26a7d73821108 Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 13:11:34 +0900 Subject: [PATCH 126/168] introducde underline and strikethrough --- include/Mw/StringDefs.h | 2 ++ milsko.xml | 8 +++++--- src/core.c | 24 ++++++++++++++++-------- src/draw.c | 4 +++- src/text/text.c | 33 +++++++++++++++++++++++++++------ 5 files changed, 53 insertions(+), 18 deletions(-) diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index cf0a723..8d00b40 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -58,6 +58,8 @@ #define MwNminute "Iminute" #define MwNsecond "Isecond" #define MwNtype "Itype" +#define MwNstrikethrough "Istrikethrough" +#define MwNunderline "Iunderline" #define MwNtitle "Stitle" #define MwNtext "Stext" diff --git a/milsko.xml b/milsko.xml index 5b90410..7a7410a 100644 --- a/milsko.xml +++ b/milsko.xml @@ -105,13 +105,15 @@ - - - + + + + + diff --git a/src/core.c b/src/core.c index 481fa34..1403310 100644 --- a/src/core.c +++ b/src/core.c @@ -69,7 +69,8 @@ static void lldrawhandler(MwLL handle, void* data) { static void lluphandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; MwMouse* p = data; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; if(p->button == MwMOUSE_LEFT) h->pressed = 0; h->mouse_point.x = p->point.x; @@ -83,7 +84,8 @@ static void lluphandler(MwLL handle, void* data) { static void lldownhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; MwMouse* p = data; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; if(p->button == MwMOUSE_LEFT) h->pressed = 1; h->mouse_point.x = p->point.x; @@ -158,7 +160,8 @@ static void llmovehandler(MwLL handle, void* data) { static void llkeyhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; int key = *(int*)data; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatch3(h, key, key); MwDispatchUserHandler(h, MwNkeyHandler, data); @@ -166,28 +169,32 @@ static void llkeyhandler(MwLL handle, void* data) { static void llkeyrelhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatchUserHandler(h, MwNkeyReleaseHandler, data); } static void llfocusinhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatchUserHandler(h, MwNfocusInHandler, data); } static void llfocusouthandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatchUserHandler(h, MwNfocusOutHandler, data); } static void llclipboardhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatch3(h, clipboard, data); MwDispatchUserHandler(h, MwNclipboardHandler, data); @@ -195,7 +202,8 @@ static void llclipboardhandler(MwLL handle, void* data) { static void lldraganddrophandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - if(MwGetInteger(h, MwNdisabled) == 1) return; + int n; + if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; MwDispatchUserHandler(h, MwNdragAndDropHandler, data); } diff --git a/src/draw.c b/src/draw.c index eb15c76..ab4c9cb 100644 --- a/src/draw.c +++ b/src/draw.c @@ -39,7 +39,9 @@ static int hex(const char* txt, int len) { } static void color_set_disabled_if_disabled(MwWidget handle, MwLLColor rgb) { - if(MwGetInteger(handle, MwNdisabled) == 1) { + int n; + + if((n = MwGetInteger(handle, MwNdisabled)) != MwDEFAULT && n) { MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { diff --git a/src/text/text.c b/src/text/text.c index 45e5886..1c9f6e6 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -82,8 +82,9 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, char* last = input; int cp; MwLLColor fadedColor = NULL; + int n; - if(MwGetInteger(handle, MwNdisabled) == 1) { + if((n = MwGetInteger(handle, MwNdisabled)) != MwDEFAULT && n) { MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { @@ -107,8 +108,10 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, input += MwUTF8ToUTF32(input, &cp); if(*input == 0 || cp == '\n') { - char* line = malloc(input - last + 1); - int i; + char* line = malloc(input - last + 1); + int i; + MwPoint l[2]; + int tw, th; if(!line) { printf("Out Of Memory\n"); @@ -134,20 +137,38 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, continue; } + tw = MwTextWidth(handle, ttf, line); + th = MwTextHeight(handle, ttf, line); + p.x = point->x; if(align == MwALIGNMENT_CENTER) { - p.x -= MwTextWidth(handle, ttf, line) / 2; + p.x -= tw / 2; } else if(align == MwALIGNMENT_END) { - p.x -= MwTextWidth(handle, ttf, line); + p.x -= tw; } + l[0].x = p.x; + l[1].x = l[0].x + tw; + #ifdef TTF if(MwFLDrawText) if(is_bitmap(handle, ttf) || ttf == NULL || MwFLDrawText(handle, ttf, &p, line, fadedColor ? fadedColor : color)) #endif bitmap_MwDrawText(handle, &p, line, is_bold(handle, ttf), fadedColor ? fadedColor : color); - p.y += MwTextHeight(handle, ttf, line); + l[0].y = l[1].y = p.y; + + if((n = MwGetInteger(handle, MwNstrikethrough)) != MwDEFAULT && n) { + MwLLLine(handle->lowlevel, l, color); + } + + if((n = MwGetInteger(handle, MwNunderline)) != MwDEFAULT && n) { + l[0].y += th / 2; + l[1].y += th / 2; + MwLLLine(handle->lowlevel, l, color); + } + + p.y += th; free(line); From 39dd112f2bd9fc4ef1aa60a4e995dca51402b403 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 21 Sep 2026 11:47:44 +0900 Subject: [PATCH 127/168] improve callback --- examples/basic/document.c | 7 ++++--- milsko.xml | 28 ++++++++++++++++++---------- pl/rules.pl | 2 +- src/backend/cairo.c | 12 ++++++------ src/widget/document.c | 6 ++++-- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/examples/basic/document.c b/examples/basic/document.c index f9529fe..cea0170 100644 --- a/examples/basic/document.c +++ b/examples/basic/document.c @@ -22,11 +22,12 @@ static void MWAPI resize_window(MwWidget handle, void* user, void* call) { } static void MWAPI layout_document(MwWidget handle, void* user, void* call) { - int height = *(int*)call; + MwRect size = *(MwRect*)call; - MwViewportSetSize(viewport, MwGetInteger(document, MwNwidth), height); + MwViewportSetSize(viewport, size.width, size.height); MwVaApply(document, - MwNheight, height, + MwNwidth, size.width, + MwNheight, size.height, NULL); } diff --git a/milsko.xml b/milsko.xml index 7a7410a..81d6e13 100644 --- a/milsko.xml +++ b/milsko.xml @@ -105,15 +105,13 @@ - - - + + + - - @@ -206,7 +204,7 @@
    - + @@ -1072,10 +1070,20 @@ - - - - + + + + + + + + + + + + + + diff --git a/pl/rules.pl b/pl/rules.pl index f12c092..7a58a97 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -66,7 +66,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); - scan_wayland_protocol("staging", "fifo", "-v1"); + scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 9dab1c1..3f1e18c 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -219,8 +219,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -264,10 +264,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/widget/document.c b/src/widget/document.c index 1f48cec..d6aec38 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -498,6 +498,7 @@ static void layout(MwWidget handle) { MwFLFont* fontstack = NULL; MwRect clickable; char* c_title = NULL; + MwRect size; arrput(fontstack, NULL); @@ -612,8 +613,9 @@ static void layout(MwWidget handle) { l->font = TOPFONT; } - y += MwTextHeight(handle, TOPFONT, "M"); - MwDispatchUserHandler(handle, MwNlayoutHandler, &y); + size.width = w; + size.height = y + MwTextHeight(handle, TOPFONT, "M"); + MwDispatchUserHandler(handle, MwNlayoutHandler, &size); arrfree(fontstack); From 2858679cc4ef80c6c0bf679aa02e6e9326043488 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 21 Sep 2026 11:57:37 +0900 Subject: [PATCH 128/168] optimize --- src/widget/document.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/widget/document.c b/src/widget/document.c index d6aec38..f71e1bc 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -59,6 +59,17 @@ static void draw(MwWidget handle) { MwFLFont font = NULL; MwPoint u_p, s_p, c_p; int u = 0, s = 0, c = 0; + int s_y = 0; + int s_h = MwGetInteger(handle, MwNheight); + MwWidget p = handle->parent; + + s_y = MwGetInteger(handle, MwNy); + while(p != NULL && p->widget_class != MwWindowClass) { + s_y += MwGetInteger(p, MwNy); + + p = p->parent; + } + s_y *= -1; u_p.x = s_p.x = c_p.x = 0; u_p.y = s_p.y = c_p.y = 0; @@ -80,6 +91,8 @@ static void draw(MwWidget handle) { p.x = l->x; p.y = l->y + MwTextHeight(handle, font, l->text) / 2; + if(p.y <= s_y || p.y >= s_y + s_h) break; + if(u || s || c) { MwPoint line[2]; int j; From f8c678ac53bee5be4005afb19317d2b192525c62 Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 21 Sep 2026 12:41:56 +0900 Subject: [PATCH 129/168] ok --- include/Mw/Core.h | 7 +++++++ include/Mw/Draw.h | 7 +++++++ src/core.c | 27 +++++++++++++++++++++++++++ src/draw.c | 32 ++++++++++++++++++++++++++++++++ src/widget/document.c | 17 +++++------------ 5 files changed, 78 insertions(+), 12 deletions(-) diff --git a/include/Mw/Core.h b/include/Mw/Core.h index 61cb085..318a8ca 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -390,6 +390,13 @@ MWDECL void MWAPI MwFreeWidget(MwWidget handle); */ MWDECL void MWAPI MwGetFrame(MwWidget handle, MwRect* rect); +/*! + * @brief Gets the clipping frame of the widget + * @param handle Widget + * @param rect Frame + */ +MWDECL void MWAPI MwGetClipFrame(MwWidget handle, MwRect* rect); + #ifdef _MILSKO MWDECL void MwForceRender_Internal(MwWidget handle); MWDECL void MwForceRender2_Internal(MwWidget handle, void* ptr); diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index ad13c60..12d3d45 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -220,6 +220,13 @@ MWDECL void MWAPI MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, */ MWDECL void MWAPI MwDrawCircle(MwWidget handle, MwRect* rect, MwLLColor color, MwLLColor background, int filled); +/*! + * @brief Calculate intersect of 2 rectangles + * @param a 1st rectangle + * @param a 2nd rectangle + */ +MWDECL void MwIntersectRect(MwRect* a, const MwRect* b); + /* text.c */ /*! diff --git a/src/core.c b/src/core.c index 1403310..7bc7065 100644 --- a/src/core.c +++ b/src/core.c @@ -1241,4 +1241,31 @@ void MwGetFrame(MwWidget handle, MwRect* rect) { rect->height = MwGetInteger(handle, MwNheight); } +void MwGetClipFrame(MwWidget handle, MwRect* rect) { + MwWidget child = handle; + MwWidget p = handle->parent; + int o_x = 0, o_y = 0; + + rect->x = 0; + rect->y = 0; + rect->width = MwGetInteger(handle, MwNwidth); + rect->height = MwGetInteger(handle, MwNheight); + while(p != NULL && p->widget_class != MwWindowClass) { + MwRect pclip; + + o_x += MwGetInteger(child, MwNx); + o_y += MwGetInteger(child, MwNy); + + pclip.x = -o_x; + pclip.y = -o_y; + pclip.width = MwGetInteger(p, MwNwidth); + pclip.height = MwGetInteger(p, MwNheight); + MwIntersectRect(rect, &pclip); + if(rect->width == 0 || rect->height == 0) break; + + child = p; + p = p->parent; + } +} + const char* MwVersionString = MwVERSION; diff --git a/src/draw.c b/src/draw.c index ab4c9cb..b2ab8b1 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1125,3 +1125,35 @@ MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { return px; } + +static int _min(int a, int b) { + return a < b ? a : b; +} + +static int _max(int a, int b) { + return a > b ? a : b; +} + +void MwIntersectRect(MwRect* a, const MwRect* b) { + int x; + int y; + int right; + int bottom; + + x = _max(a->x, b->x); + y = _max(a->y, b->y); + right = _min(a->x + a->width, b->x + b->width); + bottom = _min(a->y + a->height, b->y + b->height); + + a->x = x; + a->y = y; + + if(right <= x || bottom <= x) { + a->width = 0; + a->height = 0; + return; + } + + a->width = right - x; + a->height = bottom - y; +} diff --git a/src/widget/document.c b/src/widget/document.c index f71e1bc..eb5233d 100644 --- a/src/widget/document.c +++ b/src/widget/document.c @@ -59,17 +59,9 @@ static void draw(MwWidget handle) { MwFLFont font = NULL; MwPoint u_p, s_p, c_p; int u = 0, s = 0, c = 0; - int s_y = 0; - int s_h = MwGetInteger(handle, MwNheight); - MwWidget p = handle->parent; + MwRect clip; - s_y = MwGetInteger(handle, MwNy); - while(p != NULL && p->widget_class != MwWindowClass) { - s_y += MwGetInteger(p, MwNy); - - p = p->parent; - } - s_y *= -1; + MwGetClipFrame(handle, &clip); u_p.x = s_p.x = c_p.x = 0; u_p.y = s_p.y = c_p.y = 0; @@ -87,11 +79,12 @@ static void draw(MwWidget handle) { case MwDOCUMENT_TEXT: { MwPoint p; + int th2; p.x = l->x; - p.y = l->y + MwTextHeight(handle, font, l->text) / 2; + p.y = l->y + (th2 = MwTextHeight(handle, font, l->text) / 2); - if(p.y <= s_y || p.y >= s_y + s_h) break; + if((p.y + th2) <= clip.y || (p.y - th2) >= clip.y + clip.height) break; if(u || s || c) { MwPoint line[2]; From b1a2d4d549229149a8f4af37c657ae84a52d429b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 11:36:08 -0700 Subject: [PATCH 130/168] wayland fixes --- src/backend/wayland/interfaces.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 50a58e4..2d66493 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -17,9 +17,9 @@ static void setup_clipboard(MwLL self, struct wl_seat* wl_seat); static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); -static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat); -static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); -static bool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos); +static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat); +static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); +static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos); /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { @@ -398,7 +398,6 @@ static void wl_data_source_listener_target(void* data, (void)data; (void)wl_data_source; (void)mime_type; - printf("test\n"); }; static void wl_data_source_listener_send(void* data, struct wl_data_source* wl_data_source, @@ -591,6 +590,10 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria if(self->wayland.backbuffer.surface == surface) { curSurface = surface; } + + self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); + self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); + WAYLAND_EVENT_OP_END(self); }; @@ -780,7 +783,7 @@ static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { } }; -static bool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos) { +static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos) { MwLL topmost_parent = child; MwPoint point; MwPoint relative_mouse_pos; @@ -791,8 +794,15 @@ static bool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoi while(topmost_parent->wayland.parent) { topmost_parent = topmost_parent->wayland.parent; if(topmost_parent) { - absolute_pos.x += topmost_parent->wayland.x; - absolute_pos.y += topmost_parent->wayland.y; + /* if the topmost parent is a popup then its x/y is irrelevant to us. + * it's gonna be the position of the popup itself, and we want our + * position to be relative to the popup itself. */ + if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP) { + if(topmost_parent->wayland.x > 0) + absolute_pos.x += topmost_parent->wayland.x; + if(topmost_parent->wayland.y > 0) + absolute_pos.y += topmost_parent->wayland.y; + } } } From 4cb88fdc05e74ddb3f1a4032dca53fcf64634bb7 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 11:40:51 -0700 Subject: [PATCH 131/168] wayland: remove our widget from parent's currently held widgets on destroy --- src/backend/wayland/wayland.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index c854453..d534518 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -986,6 +986,9 @@ static void MwLLDestroyImpl(MwLL handle) { int i; struct timeval tv; int select_ret; + MwLL topmost_parent = handle; + + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; event_loop(handle); // wl_display_cancel_read(handle->wayland.display); @@ -1025,6 +1028,12 @@ static void MwLLDestroyImpl(MwLL handle) { printf("widget invalid\n"); } + for(i = 0; i < arrlen(topmost_parent->wayland.currentlyHeldWidgets); i++) { + if(topmost_parent->wayland.currentlyHeldWidgets[i] == handle) { + arrdel(topmost_parent->wayland.currentlyHeldWidgets, i); + } + } + // pthread_mutex_destroy(&handle->wayland.eventsMutex); free(handle); From e8d692f05a296064f2f37f6dc369a7219505b173 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 11:54:07 -0700 Subject: [PATCH 132/168] remove the unneeded 'wayland event start/end' macros --- include/Mw/LowLevel/Wayland.h | 6 --- src/backend/wayland/interfaces.c | 85 +++++--------------------------- src/backend/wayland/wayland.c | 3 +- 3 files changed, 14 insertions(+), 80 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 0d5a24f..83cd299 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -488,12 +488,6 @@ void MwLLWaylandFlush(MwLL handle); /* recursively dispatch the key event to focused widgets. */ void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down); -/* Standard procedure before event callbacks in Wayland */ -#define WAYLAND_EVENT_OP_START(self) - -/* Footer for WAYLAND_EVENT_OP_START */ -#define WAYLAND_EVENT_OP_END(self) - /* the two decoration manager constructs */ typedef struct zxdg_decoration_manager_v1_context { struct zxdg_decoration_manager_v1* manager; diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 2d66493..82146f6 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -72,8 +72,6 @@ static void new_protocol(void* data, struct wl_registry* registry, (void)version; (void)registry; - WAYLAND_EVENT_OP_START(self); - wayland_protocol_callback_table_t* cb = shget(self->wayland.wl_protocol_setup_map, interface); if(cb != NULL) { shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data, version)); @@ -83,8 +81,6 @@ static void new_protocol(void* data, struct wl_registry* registry, } else { // printf("unknown interface %s\n", interface); } - - WAYLAND_EVENT_OP_END(self); }; /* `wl_registry.global_remove` callback */ @@ -154,11 +150,7 @@ static void wl_data_device_enter(void* data, (void)y; (void)id; - WAYLAND_EVENT_OP_START(self); - self->ll->wayland.clipboard_serial = serial; - - WAYLAND_EVENT_OP_END(self); }; static void wl_data_device_leave(void* data, struct wl_data_device* wl_data_device) { @@ -407,12 +399,10 @@ static void wl_data_source_listener_send(void* data, (void)wl_data_source; (void)mime_type; - WAYLAND_EVENT_OP_START(self); if(self->wayland.clipboard_buffer != NULL) { write(fd, self->wayland.clipboard_buffer, strlen(self->wayland.clipboard_buffer)); close(fd); } - WAYLAND_EVENT_OP_END(self); }; static void wl_data_source_listener_cancelled(void* data, struct wl_data_source* wl_data_source); @@ -427,8 +417,6 @@ static void wl_data_source_listener_cancelled(void* data, struct wl_data_source* wl_data_source) { MwLL self = data; - WAYLAND_EVENT_OP_START(self); - if(wl_data_source) wl_data_source_destroy(wl_data_source); @@ -442,8 +430,6 @@ static void wl_data_source_listener_cancelled(void* data, wl_data_source_offer(self->wayland.clipboard_source.wl, "text/uri-list"); wl_data_source_add_listener(self->wayland.clipboard_source.wl, &wl_data_source_listener, self); - - WAYLAND_EVENT_OP_END(self); }; static void zwp_primary_selection_source_v1_send(void* data, @@ -454,22 +440,16 @@ static void zwp_primary_selection_source_v1_send(void* data, (void)wl_data_source; (void)mime_type; - WAYLAND_EVENT_OP_START(self); - if(self->wayland.clipboard_buffer != NULL) { write(fd, self->wayland.clipboard_buffer, strlen(self->wayland.clipboard_buffer)); close(fd); } - - WAYLAND_EVENT_OP_END(self); }; static void zwp_primary_selection_source_v1_cancelled(void* data, struct zwp_primary_selection_source_v1* wl_data_source) { MwLL self = data; (void)wl_data_source; - WAYLAND_EVENT_OP_START(self); - zwp_primary_selection_source_v1_destroy(self->wayland.clipboard_source.zwp); self->wayland.clipboard_source.zwp = zwp_primary_selection_device_manager_v1_create_source(self->wayland.clipboard_manager.zwp); @@ -479,8 +459,6 @@ static void zwp_primary_selection_source_v1_cancelled(void* data, zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "TEXT"); zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "STRING"); zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "UTF8_STRING"); - - WAYLAND_EVENT_OP_END(self); }; struct zwp_primary_selection_source_v1_listener zwp_primary_selection_source_v1_listener = { @@ -577,7 +555,6 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria (void)surface_y; (void)wl_pointer; - WAYLAND_EVENT_OP_START(self); while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; if(self->wayland.framebuffer.surface == surface) { @@ -593,20 +570,15 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); - - WAYLAND_EVENT_OP_END(self); }; /* `wl_pointer.leave` callback */ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface) { - MwLL self = data; + (void)data; (void)wl_pointer; (void)serial; (void)surface; - WAYLAND_EVENT_OP_START(self); - curSurface = NULL; - WAYLAND_EVENT_OP_END(self); }; static void xdg_borderless_step_mdown(MwLL self, MwMouse p, MwU32 serial) { @@ -676,15 +648,11 @@ static void relative_pointer_motion(void* data, (void)dx; (void)dy; - WAYLAND_EVENT_OP_START(self); - p.point.x = wl_fixed_to_int(dxUnaccel); p.point.y = wl_fixed_to_int(dyUnaccel); recursive_dispatch_move(self, &p); if(self->wayland.locked_pointer) zwp_locked_pointer_v1_set_cursor_position_hint(self->wayland.locked_pointer, 0, CSD_BORDER_FRAME_TOP); - - WAYLAND_EVENT_OP_END(self); } struct zwp_relative_pointer_v1_listener MwLLWaylandRelativePointerListener = @@ -716,7 +684,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time (void)time; (void)wl_pointer; - WAYLAND_EVENT_OP_START(self); while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; currentlyHeldWidgets = topmost_parent->wayland.currentlyHeldWidgets; @@ -752,8 +719,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time if(self->wayland.backbuffer.surface) { wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); } - - WAYLAND_EVENT_OP_END(self); }; static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { @@ -794,10 +759,8 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP while(topmost_parent->wayland.parent) { topmost_parent = topmost_parent->wayland.parent; if(topmost_parent) { - /* if the topmost parent is a popup then its x/y is irrelevant to us. - * it's gonna be the position of the popup itself, and we want our - * position to be relative to the popup itself. */ - if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP) { + /* if the topmost parent is a popup/subwindow then its x/y is irrelevant to us. */ + if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP && topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) { if(topmost_parent->wayland.x > 0) absolute_pos.x += topmost_parent->wayland.x; if(topmost_parent->wayland.y > 0) @@ -881,8 +844,6 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri (void)serial; (void)time; - WAYLAND_EVENT_OP_START(self); - if(self->wayland.type != MwLL_WAYLAND_POPUP) { while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; } @@ -909,19 +870,18 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri arrsetlen(self->wayland.currentlyHeldWidgets, 0); mouse_dispatch(self, p, state); - } - if(self->wayland.backbuffer.surface) { - if(!self->wayland.has_decorations && self->wayland.do_csd) { - if(state != WL_POINTER_BUTTON_STATE_RELEASED) - xdg_borderless_step_mdown(self, p, serial); - else - xdg_borderless_step_mup(self, p, serial); + + if(self->wayland.backbuffer.surface) { + if(!self->wayland.has_decorations && self->wayland.do_csd) { + if(state != WL_POINTER_BUTTON_STATE_RELEASED) + xdg_borderless_step_mdown(self, p, serial); + else + xdg_borderless_step_mup(self, p, serial); + } } } MwLLForceRender(self); - - WAYLAND_EVENT_OP_END(self); }; /* `wl_pointer.axis` callback */ @@ -984,13 +944,9 @@ static void keyboard_enter(void* data, (void)surface; (void)keys; - WAYLAND_EVENT_OP_START(self); - self->wayland.keyboard_serial = serial; MwLLDispatch(self, focus_in, NULL); - - WAYLAND_EVENT_OP_END(self); }; /* `wl_keyboard.leave` callback */ @@ -1003,11 +959,7 @@ static void keyboard_leave(void* data, (void)serial; (void)surface; - WAYLAND_EVENT_OP_START(self); - MwLLDispatch(self, focus_out, NULL); - - WAYLAND_EVENT_OP_END(self); }; void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down) { @@ -1053,8 +1005,6 @@ static void keyboard_key(void* data, while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - WAYLAND_EVENT_OP_START(self); - if(self->wayland.framebuffer.surface) { inArea |= self->wayland.framebuffer.surface == curSurface; } @@ -1072,7 +1022,7 @@ static void keyboard_key(void* data, int i; if(!self->wayland.xkb_keymap) { - WAYLAND_EVENT_OP_END(self); + return; } @@ -1087,7 +1037,7 @@ static void keyboard_key(void* data, } syms_num = xkb_keymap_key_get_syms_by_level(self->wayland.xkb_keymap, keycode, layout, level, &syms_out); if(syms_out == NULL) { - WAYLAND_EVENT_OP_END(self); + return; } @@ -1161,8 +1111,6 @@ static void keyboard_key(void* data, if(!MwWaylandVulkan) { MwLLDispatch(self, draw, NULL); } - - WAYLAND_EVENT_OP_END(self); }; /* `wl_keyboard.modifiers` callback */ @@ -1179,13 +1127,9 @@ static void keyboard_modifiers(void* data, (void)group; (void)mods_latched; - WAYLAND_EVENT_OP_START(self); - self->wayland.mod_state = 0; self->wayland.mod_state |= mods_depressed; self->wayland.mod_state |= mods_locked; - - WAYLAND_EVENT_OP_END(self); }; static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat) { @@ -1256,8 +1200,6 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, MwU32 capabilities) { MwLL self = data; - WAYLAND_EVENT_OP_START(self); - /* Always remember the seat itself, regardless of which capabilities it has - this is * both what setup_clipboard()/setup_zwp_clipboard() below use, and what lets * wl_seat_interface_destroy() release it later even on a keyboard-only seat. */ @@ -1271,7 +1213,6 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, self->wayland.pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data); } - WAYLAND_EVENT_OP_END(self); /* Only hooked up if this seat actually has a pointer: wl_data_device.get_data_device() * requires a non-null seat, and pointer_seat is only ever null before the first diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index d534518..a0645e7 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -196,9 +196,8 @@ static void xdg_toplevel_close( void* data, struct xdg_toplevel* xdg_toplevel) { MwLL self = data; (void)xdg_toplevel; - WAYLAND_EVENT_OP_START(self); + MwLLDispatch(self, close, NULL); - WAYLAND_EVENT_OP_END(self); }; /* `xdg_surface.configure` callback */ From 9420878b93ea98cdd62ee416d968de2c60920a54 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 12:01:23 -0700 Subject: [PATCH 133/168] oops! fix csd not working --- src/backend/wayland/interfaces.c | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 82146f6..31a8219 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -692,9 +692,9 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time inArea |= self->wayland.framebuffer.surface == curSurface; } - // if(self->wayland.backbuffer.surface) { - // inArea |= self->wayland.backbuffer.surface == curSurface; - // } + if(self->wayland.backbuffer.surface) { + inArea |= self->wayland.backbuffer.surface == curSurface; + } self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); @@ -854,30 +854,30 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri inArea |= self->wayland.framebuffer.surface == curSurface; } - if(inArea) { - switch(button) { - case BTN_LEFT: - p.button = MwMOUSE_LEFT; - break; - case BTN_MIDDLE: - p.button = MwMOUSE_MIDDLE; - break; - case BTN_RIGHT: - p.button = MwMOUSE_RIGHT; - break; - } - self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; + switch(button) { + case BTN_LEFT: + p.button = MwMOUSE_LEFT; + break; + case BTN_MIDDLE: + p.button = MwMOUSE_MIDDLE; + break; + case BTN_RIGHT: + p.button = MwMOUSE_RIGHT; + break; + } + if(inArea) { + self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; arrsetlen(self->wayland.currentlyHeldWidgets, 0); mouse_dispatch(self, p, state); + } - if(self->wayland.backbuffer.surface) { - if(!self->wayland.has_decorations && self->wayland.do_csd) { - if(state != WL_POINTER_BUTTON_STATE_RELEASED) - xdg_borderless_step_mdown(self, p, serial); - else - xdg_borderless_step_mup(self, p, serial); - } + if(self->wayland.backbuffer.surface) { + if(!self->wayland.has_decorations && self->wayland.do_csd) { + if(state != WL_POINTER_BUTTON_STATE_RELEASED) + xdg_borderless_step_mdown(self, p, serial); + else + xdg_borderless_step_mup(self, p, serial); } } From 954a4a8e1562dea886070b733b40f218d1cafc42 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 14:27:03 -0700 Subject: [PATCH 134/168] disable dnd on X11 for now --- examples/basic/dnd.c | 2 +- src/backend/x11.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/basic/dnd.c b/examples/basic/dnd.c index 8d0f47d..56e1c8e 100644 --- a/examples/basic/dnd.c +++ b/examples/basic/dnd.c @@ -48,7 +48,7 @@ int main() { NULL); MwAddUserHandler(window, MwNresizeHandler, resize, NULL); - MwAddUserHandler(instructions, MwNdragAndDropHandler, dnd, NULL); + MwAddUserHandler(window, MwNdragAndDropHandler, dnd, NULL); resize(window, NULL, NULL); diff --git a/src/backend/x11.c b/src/backend/x11.c index eaa64e0..b713821 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -978,6 +978,7 @@ static void MwLLNextEventImpl(MwLL handle) { }; case SelectionNotify: { +#if 0 handle->x11.clipboard_pending = 0; if(ev.xselection.property == handle->x11.xdnd_selection) { @@ -1066,6 +1067,7 @@ static void MwLLNextEventImpl(MwLL handle) { } XDeleteProperty(handle->x11.display, handle->x11.window, handle->x11.selection); } +#endif } break; } if(render) { From cb5efd9224d7e2a2648629276499b7e740f11a7c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 15:49:01 -0700 Subject: [PATCH 135/168] wayland: got resizing looking good enough --- include/Mw/LowLevel/Wayland.h | 7 ++++ src/backend/wayland/buffer.c | 65 +++++++++++++++++++++++++++++++---- src/backend/wayland/wayland.c | 10 ++---- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 83cd299..9123458 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -271,6 +271,7 @@ struct _MwLLWaylandShmBuffer { MwU8* buf; MwU8* buf_back; MwU64 buf_size; + MwU64 buf_capacity; int fd; int fd_back; MwBool setup; @@ -466,6 +467,12 @@ void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* handle); void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height); void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer); void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer); +/* Resize an already set-up shm buffer pair in place, growing the backing pool with + * wl_shm_pool_resize instead of tearing it down and recreating it from scratch. */ +void MwLLWaylandBufferResize(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height); + +void MwLLWaylandFramebufferResize(struct _MwLLWayland* wayland); +void MwLLWaylandBackbufferResize(struct _MwLLWayland* wayland); void MwLLWaylandRegionSetup(MwLL handle); void MwLLWaylandRegionInvalidate(MwLL handle); diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index 79ce72c..3b61716 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -7,7 +7,7 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { MwLLCairoFrontSetup(&wayland->cairo, wayland->framebuffer.buf_back, wayland->ww, wayland->wh); - memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size); + memset(wayland->framebuffer.buf_back, 255, wayland->framebuffer.buf_size); if(wayland->configured) wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); if(wayland->framebuffer.fifo) @@ -38,7 +38,7 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) { MwLLCairoBackSetup(&wayland->cairo, wayland->backbuffer.buf_back, w, h); - memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size); + memset(wayland->backbuffer.buf_back, 0, wayland->backbuffer.buf_size); if(wayland->configured) wl_surface_attach(wayland->backbuffer.surface, wayland->backbuffer.shm_buffer, 0, 0); // if(wayland->framebuffer.fifo) @@ -90,6 +90,8 @@ void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, M buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0); buffer->buf_back = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd_back, 0); + buffer->buf_capacity = buffer->buf_size; + fsync(buffer->fd); fsync(buffer->fd_back); @@ -108,8 +110,8 @@ void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer) { if(!buffer->setup) { return; } - if(buffer->buf) munmap(buffer->buf, buffer->buf_size); - if(buffer->buf_back) munmap(buffer->buf_back, buffer->buf_size); + if(buffer->buf) munmap(buffer->buf, buffer->buf_capacity); + if(buffer->buf_back) munmap(buffer->buf_back, buffer->buf_capacity); if(buffer->shm_buffer) wl_buffer_destroy(buffer->shm_buffer); if(buffer->shm_buffer_back) wl_buffer_destroy(buffer->shm_buffer_back); if(buffer->shm_pool) wl_shm_pool_destroy(buffer->shm_pool); @@ -119,14 +121,63 @@ void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer) { buffer->setup = MwFALSE; } +void MwLLWaylandBufferResize(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { + MwLLWaylandBufferDestroy(buffer); + MwLLWaylandBufferSetup(buffer, width, height); + memset(buffer->buf_back, 0, buffer->buf_size); + memset(buffer->buf, 0, buffer->buf_size); +} + +void MwLLWaylandFramebufferResize(struct _MwLLWayland* wayland) { + MwLLWaylandBufferResize(&wayland->framebuffer, wayland->ww, wayland->wh); + + MwLLCairoFrontDestroy(&wayland->cairo); + MwLLCairoFrontSetup(&wayland->cairo, wayland->framebuffer.buf_back, wayland->ww, wayland->wh); + + if(wayland->configured) + wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); + if(wayland->framebuffer.fifo) + wp_fifo_v1_set_barrier(wayland->framebuffer.fifo); + + wl_surface_commit(wayland->framebuffer.surface); + + MwLLWaylandHangUntilConfigured((MwLL)wayland); + MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->framebuffer); +} + +void MwLLWaylandBackbufferResize(struct _MwLLWayland* wayland) { + MwU32 w = wayland->ww; + MwU32 h = wayland->wh; + + if(wayland->type != MwLL_WAYLAND_TOPLEVEL) { + return; + } + + if(!wayland->has_decorations && wayland->do_csd) { + w += (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); + h += (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); + } + + MwLLWaylandBufferResize(&wayland->backbuffer, w, h); + + MwLLCairoBackDestroy(&wayland->cairo); + MwLLCairoBackSetup(&wayland->cairo, wayland->backbuffer.buf_back, w, h); + + if(wayland->configured) + wl_surface_attach(wayland->backbuffer.surface, wayland->backbuffer.shm_buffer, 0, 0); + wl_surface_commit(wayland->backbuffer.surface); + MwLLWaylandHangUntilConfigured((MwLL)wayland); + MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->backbuffer); +} + void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { if(self->wayland.configured) { memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); if(buffer->surface) { // Yes this is needed every time, it's how we fix weston. - if(self->wayland.configured) { - wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - } + // if(self->wayland.configured) { + // wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); + // } if(buffer->fifo) wp_fifo_v1_wait_barrier(buffer->fifo); wl_surface_commit(buffer->surface); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index a0645e7..650e949 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -173,10 +173,7 @@ static void xdg_toplevel_configure(void* data, if(self->wayland.resizing == 0) { xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); - MwLLWaylandBackbufferDestroy(&self->wayland); - MwLLWaylandBackbufferSetup(&self->wayland); - MwLLWaylandFramebufferDestroy(&self->wayland); - MwLLWaylandFramebufferSetup(&self->wayland); + MwLLWaylandFramebufferResize(&self->wayland); MwLLWaylandRegionSetup(self); MwLLDispatch(self, resize, NULL); @@ -1112,10 +1109,7 @@ static void actually_set_wh(MwLL handle) { MwLLWaylandRegionSetup(handle); if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL) recursive_render(handle); - MwLLWaylandFramebufferDestroy(&handle->wayland); - MwLLWaylandFramebufferSetup(&handle->wayland); - MwLLWaylandBackbufferDestroy(&handle->wayland); - MwLLWaylandBackbufferSetup(&handle->wayland); + MwLLWaylandFramebufferResize(&handle->wayland); MwLLDispatch(handle, draw, NULL); } From 58027c095f51bd4f68e45b0bc21a7ed3edb8c747 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 16:51:46 -0700 Subject: [PATCH 136/168] snapshot previous buffer so that we don't have ghosting anymore on rotate (this also makes resizing A Bit better) --- include/Mw/LowLevel/Wayland.h | 2 ++ src/backend/wayland/wayland.c | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 9123458..c176ee2 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -428,6 +428,8 @@ struct _MwLLWayland { MwBool do_cascading_draw; int cascading_child_num; + cairo_surface_t* snapshot; + MwBool dispatching_resize; struct _MwLLWaylandShmBuffer framebuffer; diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 650e949..24c6a1b 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -939,6 +939,13 @@ static void draw_children(MwLL handle) { cairo_reset_clip(handle->wayland.cairo.front_cairo_back); + if(handle->wayland.snapshot) { + cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface(handle->wayland.cairo.front_cairo_back, handle->wayland.snapshot, 0, 0); + cairo_paint(handle->wayland.cairo.front_cairo_back); + cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_OVER); + } + MwLLWaylandChildrenIterate(handle, draw_child); if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); @@ -1299,6 +1306,21 @@ static void MwLLEndDrawImpl(MwLL handle) { } root->wayland.do_cascading_draw = MwTRUE; + if(handle->wayland.snapshot) { + cairo_surface_destroy(handle->wayland.snapshot); + handle->wayland.snapshot = NULL; + } + if(handle->wayland.ww > 0 && handle->wayland.wh > 0) { + cairo_t* snap_cr; + + handle->wayland.snapshot = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, handle->wayland.ww, handle->wayland.wh); + snap_cr = cairo_create(handle->wayland.snapshot); + cairo_set_operator(snap_cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface(snap_cr, handle->wayland.cairo.front_cs_back, 0, 0); + cairo_paint(snap_cr); + cairo_destroy(snap_cr); + } + if(handle->wayland.configured) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); From e43a5291f5d3ddb154e5e583b84e42c78ac97f49 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 16:55:27 -0700 Subject: [PATCH 137/168] combobox fix --- src/backend/wayland/buffer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index 3b61716..dec8564 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -175,9 +175,10 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); if(buffer->surface) { // Yes this is needed every time, it's how we fix weston. - // if(self->wayland.configured) { - // wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - // } + // it's also how we fix comboboxes. + if(self->wayland.configured) { + wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); + } if(buffer->fifo) wp_fifo_v1_wait_barrier(buffer->fifo); wl_surface_commit(buffer->surface); From c2f8fb3f82ab64d24eba5f8772dd20b425153218 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 17:22:15 -0700 Subject: [PATCH 138/168] wayland: actual subsurface type for the one widget that needs it (vulkan) --- CMakeLists.txt | 2 +- examples/vkdemos/vulkan.c | 4 +- include/Mw/LowLevel/Wayland.h | 11 +++++ src/backend/wayland/interfaces.c | 15 +++---- src/backend/wayland/wayland.c | 69 ++++++++++++++++++++++++++++++++ src/widget/vulkan.c | 12 +++++- 6 files changed, 100 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f5bb780..2174649 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -467,7 +467,7 @@ if(MW_BUILD_VULKAN) ) endif() - check_include_files(vulkan/VULKAN.h HAS_VK_HEADER) + check_include_files(vulkan/vulkan.h HAS_VK_HEADER) if(HAS_VK_HEADER) target_compile_definitions( Mw diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 9060a97..6015415 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -257,8 +257,8 @@ void vulkan_setup(MwWidget handle) { swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh}, swapchainCreateInfo.imageArrayLayers = 1, swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; // th is how we specify no transformation. swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c176ee2..607ff2c 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -257,6 +257,14 @@ struct _MwLLWaylandLayerSurface { struct zwlr_layer_surface_v1* surface; }; +struct _MwLLWaylandSubsurface { + MwLL parent; + + struct xdg_surface* xdg_surface; + struct wl_subsurface* subsurface; + struct wl_subcompositor* subcompositor; +}; + /* Shared set of anything needed for a shm buffer. */ struct _MwLLWaylandShmBuffer { struct wl_shm* shm; @@ -283,6 +291,7 @@ enum _MwLLWaylandType { MwLL_WAYLAND_SUBLEVEL, MwLL_WAYLAND_POPUP, MwLL_WAYLAND_LAYER_SURFACE, + MwLL_WAYLAND_SUBSURFACE, }; typedef struct wl_clipboard_device_context { @@ -315,6 +324,8 @@ struct _MwLLWayland { struct _MwLLWaylandPopup* popup; /* Pointer for data that's only loaded if the widget is a layer surface */ struct _MwLLWaylandLayerSurface* layer_surface; + /* Pointer for data that's only loaded if the widget is a subsurface */ + struct _MwLLWaylandSubsurface* subsurface; }; enum _MwLLWaylandType type; diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 31a8219..4aebb61 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -1350,6 +1350,8 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan (void)version; if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + } else if(wayland->type == MwLL_WAYLAND_SUBSURFACE) { + wayland->subsurface->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } return NULL; @@ -1360,6 +1362,9 @@ static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, way if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wl_subcompositor_destroy(wayland->toplevel->scompositor); } + if(wayland->type == MwLL_WAYLAND_SUBSURFACE) { + wl_subcompositor_destroy(wayland->subsurface->subcompositor); + } } /* xdg_wm_base setup function */ @@ -1500,19 +1505,11 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zwp_relative_pointer_manager_v1); WL_INTERFACE(xdg_wm_base); WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ + WL_INTERFACE(wl_subcompositor); if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); - WL_INTERFACE(wl_subcompositor); - WL_INTERFACE(wl_seat); WL_INTERFACE(wp_fifo_manager_v1); - } else if(wayland->type == MwLL_WAYLAND_POPUP) { - WL_INTERFACE(wl_seat); - } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { - WL_INTERFACE(wl_subcompositor); - WL_INTERFACE(wl_seat); - } else { - WL_INTERFACE(wl_subcompositor); } #undef WL_INTERFACE } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 24c6a1b..67429f2 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -366,6 +366,8 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.sublevel->xdg_surface = parent->wayland.toplevel->xdg_surface; } else if(parent->wayland.type == MwLL_WAYLAND_SUBLEVEL) { r->wayland.sublevel->xdg_surface = parent->wayland.sublevel->xdg_surface; + } else if(parent->wayland.type == MwLL_WAYLAND_SUBSURFACE) { + r->wayland.sublevel->xdg_surface = parent->wayland.subsurface->xdg_surface; } else if(parent->wayland.type == MwLL_WAYLAND_POPUP) { r->wayland.sublevel->xdg_surface = parent->wayland.popup->xdg_surface; } @@ -396,6 +398,66 @@ static void destroy_sublevel(MwLL r) { r->wayland.configured = MwFALSE; } +/* Subsurface setup function */ +static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { + struct wl_compositor* compositor = parent->wayland.compositor; + struct wl_surface* parent_surface = parent->wayland.framebuffer.surface; + + r->wayland.subsurface = malloc(sizeof(struct _MwLLWaylandSubsurface)); + r->wayland.subsurface->parent = parent; + + r->wayland.type = MwLL_WAYLAND_SUBSURFACE; + + r->wayland.display = parent->wayland.display; + + MwLLWaylandSetupCallbacks(&r->wayland); + + r->wayland.registry = wl_display_get_registry(parent->wayland.display); + r->wayland.display = parent->wayland.display; + + if(parent->wayland.type == MwLL_WAYLAND_TOPLEVEL) { + r->wayland.subsurface->xdg_surface = parent->wayland.toplevel->xdg_surface; + } else { + r->wayland.subsurface->xdg_surface = parent->wayland.subsurface->xdg_surface; + } + + wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); + if(wl_display_roundtrip(r->wayland.display) == -1) { + printf("roundtrip failed: %d\n", wl_display_get_error(r->wayland.display)); + raise(SIGTRAP); + return; + } + + r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor); + + r->wayland.subsurface->subsurface = wl_subcompositor_get_subsurface(r->wayland.subsurface->subcompositor, r->wayland.framebuffer.surface, parent_surface); + + wl_subsurface_set_desync(r->wayland.subsurface->subsurface); + wl_subsurface_set_position(r->wayland.subsurface->subsurface, x, y); + + if(parent) { + wl_subsurface_place_above(r->wayland.subsurface->subsurface, parent->wayland.framebuffer.surface); + } + + r->wayland.xkb_keymap = parent->wayland.xkb_keymap; + r->wayland.xkb_state = parent->wayland.xkb_state; + + r->wayland.configured = MwTRUE; + + MwLLWaylandFramebufferSetup(&r->wayland); + MwLLWaylandBackbufferSetup(&r->wayland); +} + +/* Subsurface setup function */ +static void destroy_subsurface(MwLL r) { + MwLLWaylandBackbufferDestroy(&r->wayland); + MwLLWaylandFramebufferDestroy(&r->wayland); + + free(r->wayland.sublevel); + + r->wayland.configured = MwFALSE; +} + static void popup_configure(void* data, struct xdg_popup* xdg_popup, int32_t x, @@ -830,6 +892,7 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.parent = parent; r->wayland.valid = MwTRUE; + printf("type %d\n", ty); if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { setup_toplevel(r, x, y); @@ -862,6 +925,9 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh case MwLL_WAYLAND_LAYER_SURFACE: setup_layer_surface(r, x, y, width, height); break; + case MwLL_WAYLAND_SUBSURFACE: + setup_subsurface(parent, r, x, y); + break; } } @@ -1086,6 +1152,9 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { break; case MwLL_WAYLAND_UNKNOWN: break; + case MwLL_WAYLAND_SUBSURFACE: + wl_subsurface_set_position(handle->wayland.subsurface->subsurface, x, y); + break; } MwLLWaylandRegionSetup(handle); diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index acffda3..0bc0703 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -351,13 +351,22 @@ static int vulkan_surface_setup(MwWidget handle, vulkan_t* o) { if(handle->lowlevel->common.type == MwLLBackendWayland) { LOAD_VK_FUNCTION(vkCreateWaylandSurfaceKHR); - VkWaylandSurfaceCreateInfoKHR createInfo = { + VkWaylandSurfaceCreateInfoKHR createInfo; + + /* transition to a subsurface */ + MwLLBeginStateChange(handle->lowlevel); + handle->lowlevel->wayland.changing = MwTRUE; + handle->lowlevel->wayland.type_to_be = MwLL_WAYLAND_SUBSURFACE; + MwLLEndStateChange(handle->lowlevel); + + createInfo = (VkWaylandSurfaceCreateInfoKHR){ .sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, .pNext = NULL, .flags = 0, .display = handle->lowlevel->wayland.display, .surface = handle->lowlevel->wayland.framebuffer.surface, }; + VK_CMD(_vkCreateWaylandSurfaceKHR(o->vkInstance, &createInfo, NULL, &o->vkSurface)); } #endif @@ -609,6 +618,7 @@ void MwVulkanConfigure(MwVulkanConfig* cfg) { } int MwVulkanSupported(void) { + printf("[vulkan support not copmiled]\n"); return 0; } #endif From 960db8d3e35ceefe6365266e17541f8a4c8ae884 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 10:13:08 +0900 Subject: [PATCH 139/168] some fix --- examples/basic/clipboard.c | 1 - examples/basic/dnd.c | 3 +-- examples/vkdemos/vulkan.c | 4 ++-- src/core.c | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/basic/clipboard.c b/examples/basic/clipboard.c index 9d060c3..6c4a46e 100644 --- a/examples/basic/clipboard.c +++ b/examples/basic/clipboard.c @@ -45,7 +45,6 @@ static void MWAPI tick(MwWidget handle, void* user_data, void* call_data) { MwGetClipboard(handle, MwCLIPBOARD_MAIN); cur_text = text2; MwGetClipboard(handle, MwCLIPBOARD_PRIMARY); - MwForceRender(window); } int main() { diff --git a/examples/basic/dnd.c b/examples/basic/dnd.c index 56e1c8e..0ce9aef 100644 --- a/examples/basic/dnd.c +++ b/examples/basic/dnd.c @@ -44,11 +44,10 @@ int main() { NULL); text_listbox = MwVaCreateWidget(MwListBoxClass, "label", box, 25, 150, 750, 700, MwNtext, "", - MwNacceptsDnD, 1, NULL); MwAddUserHandler(window, MwNresizeHandler, resize, NULL); - MwAddUserHandler(window, MwNdragAndDropHandler, dnd, NULL); + MwAddUserHandler(instructions, MwNdragAndDropHandler, dnd, NULL); resize(window, NULL, NULL); diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 6015415..9060a97 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -257,8 +257,8 @@ void vulkan_setup(MwWidget handle) { swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh}, swapchainCreateInfo.imageArrayLayers = 1, swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; // th is how we specify no transformation. swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/src/core.c b/src/core.c index 7bc7065..0a5fd8b 100644 --- a/src/core.c +++ b/src/core.c @@ -679,7 +679,7 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { if(h->lowlevel != NULL) MwLLSetDarkTheme(h->lowlevel, n); } - if(strcmp(key, MwNacceptsDnD) == 0) { + if(strcmp(key, MwNacceptsDnD) == 0 && n) { if(handle->lowlevel != NULL) MwLLSetupDragAndDrop(handle->lowlevel); } } From bc326491b5d105cef5165a580013648c4565d78a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 20:58:41 -0700 Subject: [PATCH 140/168] dx9 --- CMakeLists.txt | 23 +++ Jenkinsfile | 8 +- NTMakefile | 21 ++- WatMakefile | 9 +- configure | 8 +- examples/CMakeLists.txt | 9 +- examples/dxdemos/CMakeLists.txt | 24 +++ examples/dxdemos/directx9.c | 93 +++++++++ include/Mw/Widget/DirectX.h | 53 ++++++ pl/rules.pl | 8 + resource/FindDirectX.cmake | 325 ++++++++++++++++++++++++++++++++ src/widget/directx.c | 96 ++++++++++ tools/genmk.pl | 36 +++- 13 files changed, 698 insertions(+), 15 deletions(-) create mode 100644 examples/dxdemos/CMakeLists.txt create mode 100644 examples/dxdemos/directx9.c create mode 100644 include/Mw/Widget/DirectX.h create mode 100644 resource/FindDirectX.cmake create mode 100644 src/widget/directx.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2174649..046f08c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,10 @@ else() option(MW_TRY_OPENGL "Try to compile OpenGL widget or not" ON) option(MW_TRY_VULKAN "Try to compile Vulkan widget or not" ON) endif() +if(${CMAKE_SYSTEM_NAME} MATCHES Windows) + option(MW_TRY_DIRECTX "Try to compile DirectX widget or not" ON) +endif() + option(MW_INSTALL_HEADERS "Install headers" ON) @@ -90,6 +94,16 @@ if(MW_TRY_VULKAN) endif() endif() +if(MW_TRY_DIRECTX) + include(${CMAKE_CURRENT_SOURCE_DIR}/resource/FindDirectX.cmake) + if(DIRECTX_FOUND) + set(MW_BUILD_DIRECTX ON) + message(STATUS "DirectX widget has been enabled") + else() + message(STATUS "DirectX widget has been disabled") + endif() +endif() + if(MW_BUILD_STATIC) message(STATUS "Building Milsko as a static library") add_library( @@ -477,6 +491,15 @@ if(MW_BUILD_VULKAN) endif() endif() +if(MW_BUILD_DIRECTX) + list(APPEND LIBRARIES ${DIRECTX_D3DX9_LIBRARIES}) + target_compile_definitions( + Mw + PRIVATE + MW_DIRECTX + ) +endif() + target_compile_definitions( Mw PRIVATE diff --git a/Jenkinsfile b/Jenkinsfile index 9b7d639..6d93874 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,7 +30,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper") + sh("./configure --enable-opengl --enable-directx --enable-vulkan --without-vulkan-string-helper") sh("make -j4") sh("mv src/libMw.so libMw64.so") archiveArtifacts("libMw64.so") @@ -42,7 +42,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --cross --target=Windows --host=i686-w64-mingw32") + sh("./configure --enable-opengl --enable-directx --cross --target=Windows --host=i686-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw32.dll") sh("mv src/libMw.dll.a libMw32.dll.a") @@ -55,7 +55,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --cross --target=Windows --host=x86_64-w64-mingw32") + sh("./configure --enable-opengl --enable-directx --cross --target=Windows --host=x86_64-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw64.dll") sh("mv src/libMw.dll.a libMw64.dll.a") @@ -80,7 +80,7 @@ pipeline { } environment { WATCOM = "/usr/watcom" - INCLUDE = "/usr/watcom/h:/usr/watcom/h/nt" + INCLUDE = "/usr/watcom/h:/usr/watcom/h/nt:/usr/watcom/h/nt/directx" PATH = "/usr/watcom/binl64:${env.PATH}" } steps { diff --git a/NTMakefile b/NTMakefile index b07f798..37b4a95 100644 --- a/NTMakefile +++ b/NTMakefile @@ -1,7 +1,20 @@ CC = cl /TC /c /nologo LD = link /nologo -MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL +!if [where d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk] +!endif +!else +!if [echo DX9_FLAGS =>dx9flags.mk] +!endif +!endif +!if exist("dx9flags.mk") +!include "dx9flags.mk" +!else +DX9_FLAGS = +!endif + +MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX9_FLAGS) MW_LDFLAGS = /DLL EXE_CFLAGS = /Iinclude EXE_LDFLAGS = @@ -86,6 +99,7 @@ clean: del /f /q src\widget\checkbox.obj del /f /q src\widget\clock.obj del /f /q src\widget\combobox.obj + del /f /q src\widget\directx.obj del /f /q src\widget\document.obj del /f /q src\widget\entry.obj del /f /q src\widget\frame.obj @@ -108,6 +122,7 @@ clean: del /f /q src\widget\window.obj del /f /q src\Mw.dll del /f /q src\Mw.lib + del /f /q dx9flags.mk del /f /q examples\basic\box.obj del /f /q examples\basic\calculator.obj del /f /q examples\basic\checkbox.obj @@ -342,8 +357,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\directx.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\directx.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index fd98079..09a942d 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,7 +1,7 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt @@ -85,6 +85,7 @@ clean: .SYMBOLIC %erase src/widget/checkbox.obj %erase src/widget/clock.obj %erase src/widget/combobox.obj + %erase src/widget/directx.obj %erase src/widget/document.obj %erase src/widget/entry.obj %erase src/widget/frame.obj @@ -341,8 +342,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/directx.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/directx.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -498,6 +499,8 @@ src/widget/clock.obj: src/widget/clock.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/clock.c src/widget/combobox.obj: src/widget/combobox.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/combobox.c +src/widget/directx.obj: src/widget/directx.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/directx.c src/widget/document.obj: src/widget/document.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/document.c src/widget/entry.obj: src/widget/entry.c diff --git a/configure b/configure index 44db66d..f6ff13b 100755 --- a/configure +++ b/configure @@ -54,6 +54,9 @@ param_set("examples", 1); # (option that only makes sense on x11) param_set("allow-sloppy-focus", 0); +# (option that only makes sense on Windows) +param_set("directx", 0); + my %features = ( "classic-theme" => "use classic theme", "stb-image" => "use stb_image, instead use libjpeg/libpng", @@ -69,7 +72,8 @@ my %features = ( "wayland" => "enable wayland backend", "gnustep" => "use gnustep", "dbus" => "use DBus on supported platform", - "allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus" + "allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus", + "directx" => "(Windows only) build DirectX widget" ); my @features_keys = ( "1classic-theme", "1stb-image", @@ -78,7 +82,7 @@ my @features_keys = ( "1vulkan", "2vulkan-string-helper", "1shared", "1static", "1wayland", "1gnustep", - "1dbus" + "1dbus", "1directx" ); sub def_platform { diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 5baed4a..4ac6962 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,7 +1,12 @@ add_subdirectory(basic) if(${MW_TRY_OPENGL}) -add_subdirectory(gldemos) + add_subdirectory(gldemos) endif() if(${MW_TRY_VULKAN}) -add_subdirectory(vkdemos) + add_subdirectory(vkdemos) +endif() +if(WIN32) + if(${MW_TRY_DIRECTX}) + add_subdirectory(dxdemos) + endif() endif() diff --git a/examples/dxdemos/CMakeLists.txt b/examples/dxdemos/CMakeLists.txt new file mode 100644 index 0000000..38265e1 --- /dev/null +++ b/examples/dxdemos/CMakeLists.txt @@ -0,0 +1,24 @@ +file( + GLOB + EXAMPLES_DIRECTX_SOURCES + *.c +) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../resource/FindDirectX.cmake) + +if(${DIRECTX_FOUND}) + foreach(PATH IN LISTS EXAMPLES_DIRECTX_SOURCES) + get_filename_component(TARGET ${PATH} NAME_WE) + add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) + target_include_directories( + ${TARGET} + PRIVATE + ${DIRECTX_INCLUDE_DIRS} + ) + target_link_libraries( + ${TARGET} + PRIVATE + Mw + ${DIRECTX_D3DX9_LIBRARIES} + ) + endforeach() +endif() diff --git a/examples/dxdemos/directx9.c b/examples/dxdemos/directx9.c new file mode 100644 index 0000000..6b28ac0 --- /dev/null +++ b/examples/dxdemos/directx9.c @@ -0,0 +1,93 @@ +/* + * Adapted from: + * http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-1 + * http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-4 + */ +#include +#include + +MwWidget window, d3d9; +LPDIRECT3D9 d3d; +LPDIRECT3DDEVICE9 d3ddev; +LPDIRECT3DVERTEXBUFFER9 v_buffer; + +struct CUSTOMVERTEX { + FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag + DWORD color; // from the D3DFVF_DIFFUSE flag +}; +#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) + +static void MWAPI draw(MwWidget handle, void* user, void* client) { + // clear the window to a deep blue + d3ddev->lpVtbl->Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); + + d3ddev->lpVtbl->BeginScene(d3ddev); // begins the 3D scene + + // select which vertex format we are using + d3ddev->lpVtbl->SetFVF(d3ddev, CUSTOMFVF); + + // select the vertex buffer to display + d3ddev->lpVtbl->SetStreamSource(d3ddev, 0, v_buffer, 0, sizeof(struct CUSTOMVERTEX)); + + // copy the vertex buffer to the back buffer + d3ddev->lpVtbl->DrawPrimitive(d3ddev, D3DPT_TRIANGLELIST, 0, 1); + + d3ddev->lpVtbl->EndScene(d3ddev); // ends the 3D scene + + d3ddev->lpVtbl->Present(d3ddev, NULL, NULL, NULL, NULL); // displays the created frame +} + +int main() { + MwLibraryInit(); + + window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); + + d3d9 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); + + d3d = MwDirectXGetD3D9(d3d9); + d3ddev = MwDirectXGetD3Dev9(d3d9); + + // create three vertices using the CUSTOMVERTEX struct built earlier + struct CUSTOMVERTEX vertices[] = + { + { + 400.0f, + 0.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(0, 0, 255), + }, + { + 800.0f, + 600.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(0, 255, 0), + }, + { + 0.0f, + 600.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(255, 0, 0), + }, + }; + + d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, + 3 * sizeof(struct CUSTOMVERTEX), + 0, + CUSTOMFVF, + D3DPOOL_MANAGED, + &v_buffer, + NULL); + + VOID* pVoid; // the void pointer + + v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (void**)&pVoid, 0); // lock the vertex buffer + memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer + v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer + + MwAddUserHandler(window, MwNtickHandler, draw, NULL); + + MwLoop(window); +} diff --git a/include/Mw/Widget/DirectX.h b/include/Mw/Widget/DirectX.h new file mode 100644 index 0000000..a81b4ae --- /dev/null +++ b/include/Mw/Widget/DirectX.h @@ -0,0 +1,53 @@ +/*! + * @file Mw/Widget/DirectX.h + * @brief DirectX widget. + * @warning Only avaliable on Windows. + */ +#ifndef __MW_WIDGET_DIRECTX_H__ +#define __MW_WIDGET_DIRECTX_H__ + +#include +#include +#include + +#if !defined(MW_DIRECTX_NO_INCLUDE) + +/* https://github.com/microsoft/Windows-classic-samples/issues/317 */ +#if defined(__MINGW32__) || defined(__MINGW64__) +#define NTDDI_VERSION 0x07000000 +#define _WIN32_WINNT 0x0A00 + +#endif + +#include +#endif + +#ifndef _WIN32 +#error DirectX widget only avaliable for Win32 backends +#endif + +/*! + * @brief D3D9 widget class + */ +MWDECL MwClass MwD3D9Class; + +#ifdef __cplusplus +extern "C" { +#endif + +MwInline LPDIRECT3D9 MwDirectXGetD3D9(MwWidget handle) { + LPDIRECT3D9 out = NULL; + MwVaWidgetExecute(handle, "mwDirectXGetD3D9", &out, NULL); + return out; +}; +MwInline LPDIRECT3DDEVICE9 MwDirectXGetD3Dev9(MwWidget handle) { + LPDIRECT3DDEVICE9 out = NULL; + MwVaWidgetExecute(handle, "mwDirectXGetD3Dev9", &out); + return out; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pl/rules.pl b/pl/rules.pl index 7a58a97..3f539ee 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -178,6 +178,7 @@ new_object("src/widget/window.c"); new_object("src/widget/opengl.c"); new_object("src/widget/vulkan.c"); +new_object("src/widget/directx.c"); if (param_get("opengl")) { add_cflags("-DMW_OPENGL"); @@ -185,6 +186,9 @@ if (param_get("opengl")) { if (param_get("vulkan")) { add_cflags("-DMW_VULKAN"); } +if (param_get("directx")) { + add_cflags("-DMW_DIRECTX"); +} new_object("src/dialog/*.c"); @@ -230,4 +234,8 @@ if (param_get("vulkan")) { new_example("examples/vkdemos/vulkan"); } +if (param_get("directx")) { + new_example("examples/dxdemos/directx9"); +} + 1; diff --git a/resource/FindDirectX.cmake b/resource/FindDirectX.cmake new file mode 100644 index 0000000..89b96ec --- /dev/null +++ b/resource/FindDirectX.cmake @@ -0,0 +1,325 @@ +# - try to find part of DirectX SDK +# +# Cache Variables: (probably not for direct use in your scripts) +# DIRECTX_INCLUDE_DIR +# +# Variables you should use in your CMakeLists.txt: +# DIRECTX_DXGUID_LIBRARY - deprecated, see below +# DIRECTX_DXERR_LIBRARY - deprecated, see http://blogs.msdn.com/b/chuckw/archive/2012/04/24/where-s-dxerr-lib.aspx +# DIRECTX_DINPUT_LIBRARY +# DIRECTX_DINPUT_INCLUDE_DIR +# DIRECTX_D3D9_LIBRARY +# DIRECTX_D3DXOF_LIBRARY +# DIRECTX_D3DX9_LIBRARIES +# DIRECTX_INCLUDE_DIRS +# DIRECTX_FOUND - if this is not true, do not attempt to use this library +# +# Defines these macros: +# find_directx_include - wrapper for find_path that provides PATHS, HINTS, and PATH_SUFFIXES. +# find_directx_library - wrapper for find_library that provides PATHS, HINTS, and PATH_SUFFIXES. +# Requires these CMake modules: +# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) +# SelectLibraryConfigurations +# +# Original Author: +# 2012 Rylie Pavlik +# https://ryliepavlik.com/ +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright 2012, Iowa State University +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# SPDX-License-Identifier: BSL-1.0 + + +set(DIRECTX_ROOT_DIR + "${DIRECTX_ROOT_DIR}" + CACHE + PATH + "Root directory to search for DirectX") + +if(MSVC) + file(TO_CMAKE_PATH "$ENV{ProgramFiles}" _PROG_FILES) + set(_PF86 "ProgramFiles(x86)") + file(TO_CMAKE_PATH "$ENV{${_PF86}}" _PROG_FILES_X86) + if(_PROG_FILES_X86) + set(_PROG_FILES "${_PROG_FILES_X86}") + endif() + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_dx_lib_suffixes lib/x64 lib) + else() + set(_dx_lib_suffixes lib/x86 lib) + endif() + set(DXSDK_DIRS) + + set(_dx_quiet) + if(DirectX_FIND_QUIETLY) + set(_dx_quiet QUIET) + endif() + find_package(WindowsSDK ${_dx_quiet}) + if(WINDOWSSDK_FOUND) + foreach(_dir ${WINDOWSSDK_DIRS}) + get_windowssdk_include_dirs(${_dir} _include_dirs) + if(_include_dirs) + list(APPEND DXSDK_DIRS ${_include_dirs}) + endif() + endforeach() + endif() + + macro(_append_dxsdk_in_inclusive_range _low _high) + if((NOT MSVC_VERSION LESS ${_low}) AND (NOT MSVC_VERSION GREATER ${_high})) + list(APPEND DXSDK_DIRS ${ARGN}) + endif() + endmacro() + _append_dxsdk_in_inclusive_range(1500 1600 "${_PROG_FILES}/Microsoft DirectX SDK (June 2010)") + _append_dxsdk_in_inclusive_range(1400 1600 + "${_PROG_FILES}/Microsoft DirectX SDK (February 2010)" + "${_PROG_FILES}/Microsoft DirectX SDK (August 2009)" + "${_PROG_FILES}/Microsoft DirectX SDK (March 2009)" + "${_PROG_FILES}/Microsoft DirectX SDK (November 2008)" + "${_PROG_FILES}/Microsoft DirectX SDK (August 2008)" + "${_PROG_FILES}/Microsoft DirectX SDK (June 2008)" + "${_PROG_FILES}/Microsoft DirectX SDK (March 2008)") + _append_dxsdk_in_inclusive_range(1310 1500 + "${_PROG_FILES}/Microsoft DirectX SDK (November 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (August 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (June 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (April 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (February 2007)" + "${_PROG_FILES}/Microsoft DirectX SDK (December 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (October 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (August 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (June 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (April 2006)" + "${_PROG_FILES}/Microsoft DirectX SDK (February 2006)") + + file(TO_CMAKE_PATH "$ENV{DXSDK_DIR}" ENV_DXSDK_DIR) + if(ENV_DXSDK_DIR) + list(APPEND DXSDK_DIRS ${ENV_DXSDK_DIR}) + endif() +else() + set(_dx_lib_suffixes lib) + set(DXSDK_DIRS /mingw) +endif() + +find_path(DIRECTX_INCLUDE_DIR + NAMES + dxdiag.h + dinput.h + dxerr8.h + PATHS + ${DXSDK_DIRS} + HINTS + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + include) +find_path(DIRECTX_DINPUT_INCLUDE_DIR + NAMES + dinput.h + PATHS + ${DXSDK_DIRS} + HINTS + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + include) + +set(DXLIB_HINTS) +if(WINDOWSSDK_FOUND AND DIRECTX_INCLUDE_DIR) + get_windowssdk_from_component("${DIRECTX_INCLUDE_DIR}" _winsdk) + if(_winsdk) + get_windowssdk_library_dirs("${_winsdk}" _libdirs) + if(_libdirs) + list(APPEND DXLIB_HINTS ${_libdirs}) + endif() + endif() +endif() + +if(WINDOWSSDK_FOUND AND DIRECTX_DINPUT_INCLUDE_DIR) + get_windowssdk_from_component("${DIRECTX_DINPUT_INCLUDE_DIR}" _winsdk) + if(_winsdk) + get_windowssdk_library_dirs("${_winsdk}" _includes) + if(_includes) + list(APPEND DXLIB_HINTS ${_includes}) + endif() + endif() +endif() + +find_library(DIRECTX_DXGUID_LIBRARY + NAMES + dxguid + PATHS + ${DXLIB_HINTS} + ${DXSDK_DIRS} + HINTS + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +if(DIRECTX_DXGUID_LIBRARY) + get_filename_component(_dxsdk_lib_dir ${DIRECTX_DXGUID_LIBRARY} PATH) + list(APPEND DXLIB_HINTS "${_dxsdk_lib_dir}") +endif() + +find_library(DIRECTX_DINPUT_LIBRARY + NAMES + dinput8 + dinput + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_DXERR_LIBRARY + NAMES + dxerr + dxerr9 + dxerr8 + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_D3D9_LIBRARY + NAMES + d3d9 + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_D3DXOF_LIBRARY + NAMES + d3dxof + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_D3DX9_LIBRARY_RELEASE + NAMES + d3dx9 + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_D3DX9_LIBRARY_DEBUG + NAMES + d3dx9d + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +find_library(DIRECTX_XINPUT_LIBRARY + NAMES + Xinput9_1_0 + Xinput + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) + +include(SelectLibraryConfigurations) +select_library_configurations(DIRECTX_D3DX9) + +set(DIRECTX_EXTRA_CHECK) +if(DIRECTX_INCLUDE_DIR) + if(MSVC80) + set(DXSDK_DEPRECATION_BUILD 1962) + endif() + + if(DXSDK_DEPRECATION_BUILD) + include(CheckCSourceCompiles) + set(_dinput_old_includes ${CMAKE_REQUIRED_INCLUDES}) + set(CMAKE_REQUIRED_INCLUDES "${DIRECTX_INCLUDE_DIR}") + check_c_source_compiles(" + #include + #if _DXSDK_BUILD_MAJOR >= ${DXSDK_DEPRECATION_BUILD} + #error + #else + int main(int argc, char * argv[]) { + return 0; + } + #endif + " + DIRECTX_SDK_SUPPORTS_COMPILER) + set(DIRECTX_EXTRA_CHECK DIRECTX_SDK_SUPPORTS_COMPILER) + set(CMAKE_REQUIRED_INCLUDES "${_dinput_old_includes}") + else() + # Until proven otherwise. + set(DIRECTX_SDK_SUPPORTS_COMPILER TRUE) + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(DirectX + DEFAULT_MSG + DIRECTX_DXGUID_LIBRARY + DIRECTX_DINPUT_LIBRARY + DIRECTX_INCLUDE_DIR + ${DIRECTX_EXTRA_CHECK}) + +if(DIRECTX_FOUND) + set(DIRECTX_LIBRARIES + "${DIRECTX_DXGUID_LIBRARY}" + "${DIRECTX_DINPUT_LIBRARY}") + + set(DIRECTX_INCLUDE_DIRS "${DIRECTX_INCLUDE_DIR}") + + mark_as_advanced(DIRECTX_ROOT_DIR) +endif() + +macro(find_directx_library) + find_library(${ARGN} + PATHS + ${DXSDK_DIRS} + HINTS + ${DXLIB_HINTS} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + ${_dx_lib_suffixes}) +endmacro() +macro(find_directx_include) + find_path(${ARGN} + PATHS + ${DXSDK_DIRS} + HINTS + ${DIRECTX_INCLUDE_DIR} + "${DIRECTX_ROOT_DIR}" + PATH_SUFFIXES + include) +endmacro() + +mark_as_advanced(DIRECTX_DINPUT_LIBRARY + DIRECTX_DXGUID_LIBRARY + DIRECTX_DXERR_LIBRARY + DIRECTX_D3D9_LIBRARY + DIRECTX_D3DXOF_LIBRARY + DIRECTX_D3DX9_LIBRARY_RELEASE + DIRECTX_D3DX9_LIBRARY_DEBUG + DIRECTX_INCLUDE_DIR) diff --git a/src/widget/directx.c b/src/widget/directx.c new file mode 100644 index 0000000..7465d69 --- /dev/null +++ b/src/widget/directx.c @@ -0,0 +1,96 @@ +#include + +#ifndef MW_DIRECTX +#define MW_DIRECTX_NO_INCLUDE +MWDECL MwClass MwDX9Class; + +MwClass MwDX9Class = NULL; +#else +#include + +typedef struct gdid3d9 { + void* d3d9dll; + IDirect3D9* (*Direct3DCreate9)(UINT sdk_version); + + LPDIRECT3D9 d3d; // the pointer to our Direct3D interface + LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class\ + +} gdid3d9_t; + +static int wcreate(MwWidget handle) { + void* r = NULL; + MwWidget w = handle; + gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); + + o->d3d9dll = LoadLibrary("d3d9.dll"); + if(!o->d3d9dll) { + MessageBox(NULL, "d3d9.dll not found! Is DirectX9 installed?", "Error", MB_OK); + ExitProcess(-1); + } + o->Direct3DCreate9 = (void*)GetProcAddress(o->d3d9dll, "Direct3DCreate9"); + + o->d3d = o->Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface + + D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information + + ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear out the struct for use + d3dpp.Windowed = TRUE; // program windowed, not fullscreen + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames + d3dpp.hDeviceWindow = handle->lowlevel->gdi.hWnd; // set the window to be used by Direct3D + + // create a device class using this information and information from the d3dpp stuct + o->d3d->lpVtbl->CreateDevice(o->d3d, + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + handle->lowlevel->gdi.hWnd, + D3DCREATE_MIXED_VERTEXPROCESSING, + &d3dpp, + &o->d3ddev); + + handle->internal = o; + + return 0; +} + +static void destroy(MwWidget handle) { + MwWidget w = handle; + gdid3d9_t* o = handle->internal; + + o->d3ddev->lpVtbl->Release(o->d3ddev); // close and release the 3D device + o->d3d->lpVtbl->Release(o->d3d); // close and release Direct3D + + free(handle->internal); +} + +static void func_handler(MwWidget handle, const char* name, void* out, + va_list va) { + gdid3d9_t* o = handle->internal; + + if(strcmp(name, "mwDirectXGetD3D9") == 0) { + *(LPDIRECT3D9*)out = o->d3d; + } + if(strcmp(name, "mwDirectXGetD3Dev9") == 0) { + *(LPDIRECT3DDEVICE9*)out = o->d3ddev; + } +} + +MwClassRec MwDX9ClassRec = {wcreate, /* create */ + destroy, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ + NULL, NULL, NULL}; +MwClass MwD3D9Class = &MwDX9ClassRec; +#endif diff --git a/tools/genmk.pl b/tools/genmk.pl index 26a7ebb..ad1495f 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -42,6 +42,23 @@ sub cobjs { return $r; } +sub dx9_detect_block { + return <<'EOF'; +!if [where d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk] +!endif +!else +!if [echo DX9_FLAGS =>dx9flags.mk] +!endif +!endif +!if exist("dx9flags.mk") +!include "dx9flags.mk" +!else +DX9_FLAGS = +!endif +EOF +} + sub generate { my ($output, $type) = @_; @@ -65,6 +82,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; + my $dx9_flags = ""; + my $dx9_block = ""; if ($type eq "Borland") { $cc = "bcc32 -c"; @@ -88,6 +107,12 @@ sub generate { $def = "/D"; $inc = "/I"; $dll = "/DLL"; + + # DX9 headers aren't part of every MSVC/Windows SDK install, so probe + # PATH for a d3d9.h at build time (on the machine actually running + # nmake) rather than baking in a yes/no here. + $dx9_flags = "\$(DX9_FLAGS)"; + $dx9_block = dx9_detect_block(); } elsif ($type eq "Watcom") { $cc = "wcc386 -bt=nt -q"; @@ -109,14 +134,20 @@ sub generate { $prefobj = "file "; $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; + + $dx9_flags = "${def}MW_DIRECTX"; } open(OUT, ">", $output); print(OUT "CC = $cc\n"); print(OUT "LD = $link\n"); print(OUT "\n"); + if ($dx9_block ne "") { + print(OUT $dx9_block); + print(OUT "\n"); + } print(OUT -"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL\n" +"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx9_flags}\n" ); print(OUT "MW_LDFLAGS = $dll\n"); print(OUT "EXE_CFLAGS = ${inc}include\n"); @@ -152,6 +183,9 @@ sub generate { } print(OUT " $del src${dir}Mw.dll\n"); print(OUT " $del src${dir}Mw.lib\n"); + if ($dx9_block ne "") { + print(OUT " $del dx9flags.mk\n"); + } foreach my $f (@examples) { my $b = $f; $b =~ s/\.c$/.obj/; From 47c9f8df4e55741595ab61c3219ff6e6b3c6fb2d Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 21:44:55 -0700 Subject: [PATCH 141/168] d3d8 too --- CMakeLists.txt | 37 +++++--- NTMakefile | 4 +- WatMakefile | 2 +- examples/CMakeLists.txt | 3 +- examples/dxdemos/CMakeLists.txt | 11 ++- examples/dxdemos/d3d8.c | 91 ++++++++++++++++++++ examples/dxdemos/{directx9.c => d3d9.c} | 14 ++-- include/Mw/Widget/D3D8.h | 55 ++++++++++++ include/Mw/Widget/{DirectX.h => D3D9.h} | 17 ++-- src/widget/d3d8.c | 107 ++++++++++++++++++++++++ src/widget/{directx.c => d3d9.c} | 48 +++++------ tools/genmk.pl | 32 +++++-- 12 files changed, 355 insertions(+), 66 deletions(-) create mode 100644 examples/dxdemos/d3d8.c rename examples/dxdemos/{directx9.c => d3d9.c} (90%) create mode 100644 include/Mw/Widget/D3D8.h rename include/Mw/Widget/{DirectX.h => D3D9.h} (83%) create mode 100644 src/widget/d3d8.c rename src/widget/{directx.c => d3d9.c} (68%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 046f08c..fa1644d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,8 +32,10 @@ else() option(MW_TRY_OPENGL "Try to compile OpenGL widget or not" ON) option(MW_TRY_VULKAN "Try to compile Vulkan widget or not" ON) endif() + if(${CMAKE_SYSTEM_NAME} MATCHES Windows) - option(MW_TRY_DIRECTX "Try to compile DirectX widget or not" ON) + option(MW_TRY_D3D8 "Try to compile D3D8 widget or not" ON) + option(MW_TRY_D3D9 "Try to compile D3D9 widget or not" ON) endif() @@ -94,13 +96,19 @@ if(MW_TRY_VULKAN) endif() endif() -if(MW_TRY_DIRECTX) +if(MW_TRY_D3D8 OR MW_TRY_D3D9) include(${CMAKE_CURRENT_SOURCE_DIR}/resource/FindDirectX.cmake) if(DIRECTX_FOUND) - set(MW_BUILD_DIRECTX ON) - message(STATUS "DirectX widget has been enabled") + if(MW_TRY_D3D8) + set(MW_BUILD_D3D8 ON) + message(STATUS "D3D8 widget has been enabled") + endif() + if(MW_TRY_D3D9) + set(MW_BUILD_D3D9 ON) + message(STATUS "D3D9 widget has been enabled") + endif() else() - message(STATUS "DirectX widget has been disabled") + message(STATUS "DirectX widgets have been disabled (DirectX not found)") endif() endif() @@ -491,13 +499,20 @@ if(MW_BUILD_VULKAN) endif() endif() -if(MW_BUILD_DIRECTX) - list(APPEND LIBRARIES ${DIRECTX_D3DX9_LIBRARIES}) +if(MW_BUILD_D3D8) target_compile_definitions( - Mw - PRIVATE - MW_DIRECTX - ) + Mw + PUBLIC + MW_DIRECTX8 + ) +endif() + +if(MW_BUILD_D3D9) + target_compile_definitions( + Mw + PUBLIC + MW_DIRECTX9 + ) endif() target_compile_definitions( diff --git a/NTMakefile b/NTMakefile index 37b4a95..12b6446 100644 --- a/NTMakefile +++ b/NTMakefile @@ -2,7 +2,7 @@ CC = cl /TC /c /nologo LD = link /nologo !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] @@ -14,7 +14,7 @@ LD = link /nologo DX9_FLAGS = !endif -MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX9_FLAGS) +MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX8_FLAGS) $(DX9_FLAGS) MW_LDFLAGS = /DLL EXE_CFLAGS = /Iinclude EXE_LDFLAGS = diff --git a/WatMakefile b/WatMakefile index 09a942d..9c7f089 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,7 +1,7 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX8 -dMW_DIRECTX9 MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4ac6962..87225f1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,8 +5,9 @@ endif() if(${MW_TRY_VULKAN}) add_subdirectory(vkdemos) endif() + if(WIN32) - if(${MW_TRY_DIRECTX}) + if(${MW_TRY_D3D8} OR ${MW_BUILD_D3D8}) add_subdirectory(dxdemos) endif() endif() diff --git a/examples/dxdemos/CMakeLists.txt b/examples/dxdemos/CMakeLists.txt index 38265e1..aa09d63 100644 --- a/examples/dxdemos/CMakeLists.txt +++ b/examples/dxdemos/CMakeLists.txt @@ -8,17 +8,16 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../../resource/FindDirectX.cmake) if(${DIRECTX_FOUND}) foreach(PATH IN LISTS EXAMPLES_DIRECTX_SOURCES) get_filename_component(TARGET ${PATH} NAME_WE) - add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) + add_executable(${TARGET} ${PATH}) target_include_directories( ${TARGET} PRIVATE ${DIRECTX_INCLUDE_DIRS} ) target_link_libraries( - ${TARGET} - PRIVATE - Mw - ${DIRECTX_D3DX9_LIBRARIES} - ) +${TARGET} +PRIVATE +Mw +) endforeach() endif() diff --git a/examples/dxdemos/d3d8.c b/examples/dxdemos/d3d8.c new file mode 100644 index 0000000..400adc6 --- /dev/null +++ b/examples/dxdemos/d3d8.c @@ -0,0 +1,91 @@ +/* + * Adapted from: + * https://web.archive.org/web/20211126225651/https://www.codeguru.com/multimedia/using-direct3d8-the-basics/ + */ +#include +#include + +MwWidget window, d3d8; +LPDIRECT3D8 d3d; +LPDIRECT3DDEVICE8 d3ddev; +LPDIRECT3DVERTEXBUFFER8 v_buffer; + +struct CUSTOMVERTEX { + FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag + DWORD color; // from the D3DFVF_DIFFUSE flag +}; +#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) + +static void MWAPI draw(MwWidget handle, void* user, void* client) { + // clear the window to a deep blue + d3ddev->lpVtbl->Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); + + d3ddev->lpVtbl->BeginScene(d3ddev); // begins the 3D scene + + // select which vertex format we are using + d3ddev->lpVtbl->SetVertexShader(d3ddev, CUSTOMFVF); + + // select the vertex buffer to display + d3ddev->lpVtbl->SetStreamSource(d3ddev, 0, v_buffer, sizeof(struct CUSTOMVERTEX)); + + // // copy the vertex buffer to the back buffer + d3ddev->lpVtbl->DrawPrimitive(d3ddev, D3DPT_TRIANGLELIST, 0, 1); + + d3ddev->lpVtbl->EndScene(d3ddev); // ends the 3D scene + + d3ddev->lpVtbl->Present(d3ddev, NULL, NULL, NULL, NULL); // displays the created frame +} + +int main() { + BYTE* pVoid; + + MwLibraryInit(); + + window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); + + d3d8 = MwCreateWidget(MwD3D8Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); + + d3d = MwDirectXGetD3D8(d3d8); + d3ddev = MwDirectXGetD3Dev8(d3d8); + + // create three vertices using the CUSTOMVERTEX struct built earlier + struct CUSTOMVERTEX vertices[] = + { + { + 400.0f, + 0.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(0, 0, 255), + }, + { + 800.0f, + 600.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(0, 255, 0), + }, + { + 0.0f, + 600.0f, + 0.5f, + 1.0f, + D3DCOLOR_XRGB(255, 0, 0), + }, + }; + + d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, + 3 * sizeof(struct CUSTOMVERTEX), + 0, + CUSTOMFVF, + D3DPOOL_MANAGED, + &v_buffer); + + v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (BYTE**)&pVoid, 0); // lock the vertex buffer + memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer + v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer + + MwAddUserHandler(window, MwNtickHandler, draw, NULL); + + MwLoop(window); +} diff --git a/examples/dxdemos/directx9.c b/examples/dxdemos/d3d9.c similarity index 90% rename from examples/dxdemos/directx9.c rename to examples/dxdemos/d3d9.c index 6b28ac0..5975739 100644 --- a/examples/dxdemos/directx9.c +++ b/examples/dxdemos/d3d9.c @@ -4,9 +4,9 @@ * http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-4 */ #include -#include +#include -MwWidget window, d3d9; +MwWidget window, d3d8; LPDIRECT3D9 d3d; LPDIRECT3DDEVICE9 d3ddev; LPDIRECT3DVERTEXBUFFER9 v_buffer; @@ -38,14 +38,16 @@ static void MWAPI draw(MwWidget handle, void* user, void* client) { } int main() { + VOID* pVoid; + MwLibraryInit(); window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); - d3d9 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); + d3d8 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - d3d = MwDirectXGetD3D9(d3d9); - d3ddev = MwDirectXGetD3Dev9(d3d9); + d3d = MwDirectXGetD3D9(d3d8); + d3ddev = MwDirectXGetD3Dev9(d3d8); // create three vertices using the CUSTOMVERTEX struct built earlier struct CUSTOMVERTEX vertices[] = @@ -81,8 +83,6 @@ int main() { &v_buffer, NULL); - VOID* pVoid; // the void pointer - v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (void**)&pVoid, 0); // lock the vertex buffer memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer diff --git a/include/Mw/Widget/D3D8.h b/include/Mw/Widget/D3D8.h new file mode 100644 index 0000000..022e7bc --- /dev/null +++ b/include/Mw/Widget/D3D8.h @@ -0,0 +1,55 @@ +/*! + * @file Mw/Widget/D3D8.h + * @brief D3D8 widget. + * @warning Only avaliable on Windows. + */ +#ifndef __MW_WIDGET_D3D8_H__ +#define __MW_WIDGET_D3D8_H__ + +#include +#include +#include + +#if !defined(MW_D3D8_NO_INCLUDE) + +/* https://github.com/microsoft/Windows-classic-samples/issues/317 */ +#if defined(__MINGW32__) || defined(__MINGW64__) +#define NTDDI_VERSION 0x07000000 +#define _WIN32_WINNT 0x0A00 + +#endif +#endif + +#ifndef _WIN32 +#error D3D8 widget only avaliable for Win32 backends +#else +#ifdef MW_DIRECTX8 +#include +#endif +#endif + +/*! + * @brief D3D8 widget class + */ +MWDECL MwClass MwD3D8Class; + +#ifdef __cplusplus +extern "C" { +#endif + +MwInline LPDIRECT3D8 MwDirectXGetD3D8(MwWidget handle) { + LPDIRECT3D8 out = NULL; + MwVaWidgetExecute(handle, "mwDirectXGetD3D8", &out, NULL); + return out; +}; +MwInline LPDIRECT3DDEVICE8 MwDirectXGetD3Dev8(MwWidget handle) { + LPDIRECT3DDEVICE8 out = NULL; + MwVaWidgetExecute(handle, "mwDirectXGetD3Dev8", &out); + return out; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/Mw/Widget/DirectX.h b/include/Mw/Widget/D3D9.h similarity index 83% rename from include/Mw/Widget/DirectX.h rename to include/Mw/Widget/D3D9.h index a81b4ae..2639e17 100644 --- a/include/Mw/Widget/DirectX.h +++ b/include/Mw/Widget/D3D9.h @@ -3,27 +3,28 @@ * @brief DirectX widget. * @warning Only avaliable on Windows. */ -#ifndef __MW_WIDGET_DIRECTX_H__ -#define __MW_WIDGET_DIRECTX_H__ +#ifndef __MW_WIDGET_D3D9_H__ +#define __MW_WIDGET_D3D9_H__ #include #include #include -#if !defined(MW_DIRECTX_NO_INCLUDE) +#if !defined(MW_D3D9_NO_INCLUDE) /* https://github.com/microsoft/Windows-classic-samples/issues/317 */ #if defined(__MINGW32__) || defined(__MINGW64__) #define NTDDI_VERSION 0x07000000 #define _WIN32_WINNT 0x0A00 - -#endif - -#include #endif #ifndef _WIN32 -#error DirectX widget only avaliable for Win32 backends +#error D3D9 widget only avaliable for Win32 backends +#else +#ifdef MW_DIRECTX9 +#include +#endif +#endif #endif /*! diff --git a/src/widget/d3d8.c b/src/widget/d3d8.c new file mode 100644 index 0000000..13e656d --- /dev/null +++ b/src/widget/d3d8.c @@ -0,0 +1,107 @@ +#include + +#ifndef MW_DIRECTX8 +#define MW_DIRECTX8_NO_INCLUDE +MWDECL MwClass MwDX8Class; + +MwClass MwDX8Class = NULL; +#else +#include + +typedef struct gdid3d8 { + void* d3d8dll; + IDirect3D8* (*Direct3DCreate8)(UINT sdk_version); + + LPDIRECT3D8 d3d; // the pointer to our Direct3D interface + LPDIRECT3DDEVICE8 d3ddev; // the pointer to the device class\ + +} gdid3d8_t; + +static int wcreate_d3d8(MwWidget handle) { + void* r = NULL; + MwWidget w = handle; + gdid3d8_t* o = malloc(sizeof(gdid3d8_t)); + D3DPRESENT_PARAMETERS d3dpp; + D3DDISPLAYMODE dispMode; + + o->d3d8dll = LoadLibrary("d3d8.dll"); + if(!o->d3d8dll) { + MessageBox(NULL, "d3d8.dll not found! Is DirectX8 installed?", "Error", MB_OK); + ExitProcess(-1); + } + o->Direct3DCreate8 = (void*)GetProcAddress(o->d3d8dll, "Direct3DCreate8"); + if(!o->Direct3DCreate8) { + MessageBox(NULL, "Direct3DCreate8 not found! Is DirectX8 installed properly?", "Error", MB_OK); + ExitProcess(-1); + } + + o->d3d = o->Direct3DCreate8(D3D_SDK_VERSION); + + o->d3d->lpVtbl->GetAdapterDisplayMode(o->d3d, D3DADAPTER_DEFAULT, &dispMode); + + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.hDeviceWindow = handle->lowlevel->gdi.hWnd; + d3dpp.BackBufferFormat = dispMode.Format; + d3dpp.EnableAutoDepthStencil = TRUE; + d3dpp.AutoDepthStencilFormat = D3DFMT_D16; + + // create a device class using this information and information from the d3dpp stuct + o->d3d->lpVtbl->CreateDevice(o->d3d, + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + handle->lowlevel->gdi.hWnd, + D3DCREATE_MIXED_VERTEXPROCESSING, + &d3dpp, + &o->d3ddev); + + o->d3ddev->lpVtbl->SetRenderState(o->d3ddev, D3DRS_LIGHTING, FALSE); + + handle->internal = o; + + return 0; +} + +static void destroy_d3d8(MwWidget handle) { + MwWidget w = handle; + gdid3d8_t* o = handle->internal; + + o->d3ddev->lpVtbl->Release(o->d3ddev); // close and release the 3D device + o->d3d->lpVtbl->Release(o->d3d); // close and release Direct3D + + free(handle->internal); +} + +static void func_handler_d3d8(MwWidget handle, const char* name, void* out, + va_list va) { + gdid3d8_t* o = handle->internal; + + if(strcmp(name, "mwDirectXGetD3D8") == 0) { + *(LPDIRECT3D8*)out = o->d3d; + } + if(strcmp(name, "mwDirectXGetD3Dev8") == 0) { + *(LPDIRECT3DDEVICE8*)out = o->d3ddev; + } +} + +MwClassRec MwDX8ClassRec = {wcreate_d3d8, /* create */ + destroy_d3d8, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler_d3d8, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ + NULL, NULL, NULL}; +MwClass MwD3D8Class = &MwDX8ClassRec; +#endif diff --git a/src/widget/directx.c b/src/widget/d3d9.c similarity index 68% rename from src/widget/directx.c rename to src/widget/d3d9.c index 7465d69..f6fc5d9 100644 --- a/src/widget/directx.c +++ b/src/widget/d3d9.c @@ -1,12 +1,12 @@ #include -#ifndef MW_DIRECTX -#define MW_DIRECTX_NO_INCLUDE +#ifndef MW_DIRECTX9 +#define MW_DIRECTX9_NO_INCLUDE MWDECL MwClass MwDX9Class; MwClass MwDX9Class = NULL; #else -#include +#include typedef struct gdid3d9 { void* d3d9dll; @@ -17,7 +17,7 @@ typedef struct gdid3d9 { } gdid3d9_t; -static int wcreate(MwWidget handle) { +static int wcreate_d3d9(MwWidget handle) { void* r = NULL; MwWidget w = handle; gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); @@ -52,7 +52,7 @@ static int wcreate(MwWidget handle) { return 0; } -static void destroy(MwWidget handle) { +static void destroy_d3d9(MwWidget handle) { MwWidget w = handle; gdid3d9_t* o = handle->internal; @@ -62,8 +62,8 @@ static void destroy(MwWidget handle) { free(handle->internal); } -static void func_handler(MwWidget handle, const char* name, void* out, - va_list va) { +static void func_handler_d3d9(MwWidget handle, const char* name, void* out, + va_list va) { gdid3d9_t* o = handle->internal; if(strcmp(name, "mwDirectXGetD3D9") == 0) { @@ -74,23 +74,23 @@ static void func_handler(MwWidget handle, const char* name, void* out, } } -MwClassRec MwDX9ClassRec = {wcreate, /* create */ - destroy, /* destroy */ - NULL, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - NULL, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ +MwClassRec MwDX9ClassRec = {wcreate_d3d9, /* create */ + destroy_d3d9, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler_d3d9, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ NULL, NULL, NULL}; MwClass MwD3D9Class = &MwDX9ClassRec; #endif diff --git a/tools/genmk.pl b/tools/genmk.pl index ad1495f..a249e24 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -42,10 +42,28 @@ sub cobjs { return $r; } + +sub dx8_detect_block { + return <<'EOF'; +!if [where d3d8.h >nul 2>nul] +!if [for /f "delims=" %P in ('where d3d8.h 2^>nul') do @echo DX8_FLAGS = /DMW_DIRECTX8 /I"%~dpP">dx8flags.mk] +!endif +!else +!if [echo DX8_FLAGS =>dx9flags.mk] +!endif +!endif +!if exist("dx8flags.mk") +!include "dx8flags.mk" +!else +DX8_FLAGS = +!endif +EOF +} + sub dx9_detect_block { return <<'EOF'; !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] @@ -82,6 +100,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; + my $dx8_flags = ""; + my $dx8_block = ""; my $dx9_flags = ""; my $dx9_block = ""; @@ -108,9 +128,8 @@ sub generate { $inc = "/I"; $dll = "/DLL"; - # DX9 headers aren't part of every MSVC/Windows SDK install, so probe - # PATH for a d3d9.h at build time (on the machine actually running - # nmake) rather than baking in a yes/no here. + $dx8_flags = "\$(DX8_FLAGS)"; + $dx8_block = dx8_detect_block(); $dx9_flags = "\$(DX9_FLAGS)"; $dx9_block = dx9_detect_block(); } @@ -135,7 +154,8 @@ sub generate { $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - $dx9_flags = "${def}MW_DIRECTX"; + $dx8_flags = "${def}MW_DIRECTX8"; + $dx9_flags = "${def}MW_DIRECTX9"; } open(OUT, ">", $output); @@ -147,7 +167,7 @@ sub generate { print(OUT "\n"); } print(OUT -"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx9_flags}\n" +"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx8_flags} ${dx9_flags}\n" ); print(OUT "MW_LDFLAGS = $dll\n"); print(OUT "EXE_CFLAGS = ${inc}include\n"); From 87cbb582f76c8aa9cecad228852b9aa86c37c7cf Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:02:27 -0700 Subject: [PATCH 142/168] perl --- configure | 8 +++++--- examples/dxdemos/d3d8.c | 4 ++++ examples/dxdemos/d3d9.c | 4 ++++ include/Mw/Widget/D3D8.h | 12 ++++++++++++ include/Mw/Widget/D3D9.h | 12 ++++++++++++ pl/rules.pl | 18 +++++++++++++----- src/widget/d3d8.c | 12 +++++------- src/widget/d3d9.c | 12 +++++------- tools/gendcl.pl | 2 ++ 9 files changed, 62 insertions(+), 22 deletions(-) diff --git a/configure b/configure index f6ff13b..a2d0ba6 100755 --- a/configure +++ b/configure @@ -55,7 +55,8 @@ param_set("examples", 1); param_set("allow-sloppy-focus", 0); # (option that only makes sense on Windows) -param_set("directx", 0); +param_set("dxd8", 0); +param_set("dxd9", 0); my %features = ( "classic-theme" => "use classic theme", @@ -73,7 +74,8 @@ my %features = ( "gnustep" => "use gnustep", "dbus" => "use DBus on supported platform", "allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus", - "directx" => "(Windows only) build DirectX widget" + "directx8" => "(Windows only) build DXD8 widget", + "directx9" => "(Windows only) build DXD9 widget" ); my @features_keys = ( "1classic-theme", "1stb-image", @@ -82,7 +84,7 @@ my @features_keys = ( "1vulkan", "2vulkan-string-helper", "1shared", "1static", "1wayland", "1gnustep", - "1dbus", "1directx" + "1dbus", "1direct8", "1directx9" ); sub def_platform { diff --git a/examples/dxdemos/d3d8.c b/examples/dxdemos/d3d8.c index 400adc6..2ef08a3 100644 --- a/examples/dxdemos/d3d8.c +++ b/examples/dxdemos/d3d8.c @@ -5,6 +5,8 @@ #include #include +#ifdef MW_DIRECTX8 + MwWidget window, d3d8; LPDIRECT3D8 d3d; LPDIRECT3DDEVICE8 d3ddev; @@ -89,3 +91,5 @@ int main() { MwLoop(window); } + +#endif diff --git a/examples/dxdemos/d3d9.c b/examples/dxdemos/d3d9.c index 5975739..9fe685c 100644 --- a/examples/dxdemos/d3d9.c +++ b/examples/dxdemos/d3d9.c @@ -6,6 +6,8 @@ #include #include +#ifdef MW_DIRECTX9 + MwWidget window, d3d8; LPDIRECT3D9 d3d; LPDIRECT3DDEVICE9 d3ddev; @@ -91,3 +93,5 @@ int main() { MwLoop(window); } + +#endif diff --git a/include/Mw/Widget/D3D8.h b/include/Mw/Widget/D3D8.h index 022e7bc..ee1bf05 100644 --- a/include/Mw/Widget/D3D8.h +++ b/include/Mw/Widget/D3D8.h @@ -22,6 +22,7 @@ #ifndef _WIN32 #error D3D8 widget only avaliable for Win32 backends +#undef MW_DIRECTX8 #else #ifdef MW_DIRECTX8 #include @@ -37,6 +38,7 @@ MWDECL MwClass MwD3D8Class; extern "C" { #endif +#ifdef MW_DIRECTX8 MwInline LPDIRECT3D8 MwDirectXGetD3D8(MwWidget handle) { LPDIRECT3D8 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3D8", &out, NULL); @@ -47,6 +49,16 @@ MwInline LPDIRECT3DDEVICE8 MwDirectXGetD3Dev8(MwWidget handle) { MwVaWidgetExecute(handle, "mwDirectXGetD3Dev8", &out); return out; }; +#else +MwInline void* MwDirectXGetD3D8(MwWidget handle) { + (void)handle; + return NULL; +}; +MwInline void* MwDirectXGetD3Dev8(MwWidget handle) { + (void)handle; + return NULL; +}; +#endif #ifdef __cplusplus } diff --git a/include/Mw/Widget/D3D9.h b/include/Mw/Widget/D3D9.h index 2639e17..e7a7149 100644 --- a/include/Mw/Widget/D3D9.h +++ b/include/Mw/Widget/D3D9.h @@ -20,6 +20,7 @@ #ifndef _WIN32 #error D3D9 widget only avaliable for Win32 backends +#undef MW_DIRECTX9 #else #ifdef MW_DIRECTX9 #include @@ -36,6 +37,7 @@ MWDECL MwClass MwD3D9Class; extern "C" { #endif +#ifdef MW_DIRECTX9 MwInline LPDIRECT3D9 MwDirectXGetD3D9(MwWidget handle) { LPDIRECT3D9 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3D9", &out, NULL); @@ -46,6 +48,16 @@ MwInline LPDIRECT3DDEVICE9 MwDirectXGetD3Dev9(MwWidget handle) { MwVaWidgetExecute(handle, "mwDirectXGetD3Dev9", &out); return out; }; +#else +MwInline void* MwDirectXGetD3D9(MwWidget handle) { + (void)handle; + return NULL; +}; +MwInline void* MwDirectXGetD3Dev9(MwWidget handle) { + (void)handle; + return NULL; +}; +#endif #ifdef __cplusplus } diff --git a/pl/rules.pl b/pl/rules.pl index 3f539ee..76ab9b4 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -178,7 +178,8 @@ new_object("src/widget/window.c"); new_object("src/widget/opengl.c"); new_object("src/widget/vulkan.c"); -new_object("src/widget/directx.c"); +new_object("src/widget/d3d8.c"); +new_object("src/widget/d3d9.c"); if (param_get("opengl")) { add_cflags("-DMW_OPENGL"); @@ -186,8 +187,11 @@ if (param_get("opengl")) { if (param_get("vulkan")) { add_cflags("-DMW_VULKAN"); } -if (param_get("directx")) { - add_cflags("-DMW_DIRECTX"); +if (param_get("directx8")) { + add_cflags("-DMW_DIRECTX8"); +} +if (param_get("directx9")) { + add_cflags("-DMW_DIRECTX9"); } new_object("src/dialog/*.c"); @@ -234,8 +238,12 @@ if (param_get("vulkan")) { new_example("examples/vkdemos/vulkan"); } -if (param_get("directx")) { - new_example("examples/dxdemos/directx9"); +if (param_get("directx8")) { + new_example("examples/dxdemos/d3d8"); +} + +if (param_get("directx9")) { + new_example("examples/dxdemos/d3d9"); } 1; diff --git a/src/widget/d3d8.c b/src/widget/d3d8.c index 13e656d..0663321 100644 --- a/src/widget/d3d8.c +++ b/src/widget/d3d8.c @@ -1,13 +1,7 @@ #include -#ifndef MW_DIRECTX8 -#define MW_DIRECTX8_NO_INCLUDE -MWDECL MwClass MwDX8Class; - -MwClass MwDX8Class = NULL; -#else +#ifdef MW_DIRECTX8 #include - typedef struct gdid3d8 { void* d3d8dll; IDirect3D8* (*Direct3DCreate8)(UINT sdk_version); @@ -104,4 +98,8 @@ MwClassRec MwDX8ClassRec = {wcreate_d3d8, /* create */ NULL, /* props_change */ NULL, NULL, NULL}; MwClass MwD3D8Class = &MwDX8ClassRec; +#else +MWDECL MwClass MwDX8Class; + +MwClass MwDX8Class = NULL; #endif diff --git a/src/widget/d3d9.c b/src/widget/d3d9.c index f6fc5d9..3246caf 100644 --- a/src/widget/d3d9.c +++ b/src/widget/d3d9.c @@ -1,13 +1,7 @@ #include -#ifndef MW_DIRECTX9 -#define MW_DIRECTX9_NO_INCLUDE -MWDECL MwClass MwDX9Class; - -MwClass MwDX9Class = NULL; -#else +#ifdef MW_DIRECTX9 #include - typedef struct gdid3d9 { void* d3d9dll; IDirect3D9* (*Direct3DCreate9)(UINT sdk_version); @@ -93,4 +87,8 @@ MwClassRec MwDX9ClassRec = {wcreate_d3d9, /* create */ NULL, /* props_change */ NULL, NULL, NULL}; MwClass MwD3D9Class = &MwDX9ClassRec; +#else +MWDECL MwClass MwDX9Class; + +MwClass MwDX9Class = NULL; #endif diff --git a/tools/gendcl.pl b/tools/gendcl.pl index f2e3399..ccc29dc 100755 --- a/tools/gendcl.pl +++ b/tools/gendcl.pl @@ -59,6 +59,8 @@ sub scan { while (my $file = readdir($dh)) { if ( !(($dir . "/" . $file) eq "src/widget/opengl.c") && !(($dir . "/" . $file) eq "src/widget/vulkan.c") + && !(($dir . "/" . $file) eq "src/widget/d3d8.c") + && !(($dir . "/" . $file) eq "src/widget/d3d9.c") && !(($dir . "/" . $file) eq "external/stb_truetype.c") && !(($dir . "/" . $file) eq "external/stb_image.c") && ($file =~ /\.c$/)) From 2a19c5e5cf6bb61cab59b4f8c9e7a0695ee6c03e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:05:40 -0700 Subject: [PATCH 143/168] genmk --- NTMakefile | 7 ++++--- WatMakefile | 13 ++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/NTMakefile b/NTMakefile index 12b6446..f42873b 100644 --- a/NTMakefile +++ b/NTMakefile @@ -99,7 +99,8 @@ clean: del /f /q src\widget\checkbox.obj del /f /q src\widget\clock.obj del /f /q src\widget\combobox.obj - del /f /q src\widget\directx.obj + del /f /q src\widget\d3d8.obj + del /f /q src\widget\d3d9.obj del /f /q src\widget\document.obj del /f /q src\widget\entry.obj del /f /q src\widget\frame.obj @@ -357,8 +358,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\directx.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\directx.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\d3d8.obj src\widget\d3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\d3d8.obj src\widget\d3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index 9c7f089..55bc6b8 100644 --- a/WatMakefile +++ b/WatMakefile @@ -85,7 +85,8 @@ clean: .SYMBOLIC %erase src/widget/checkbox.obj %erase src/widget/clock.obj %erase src/widget/combobox.obj - %erase src/widget/directx.obj + %erase src/widget/d3d8.obj + %erase src/widget/d3d9.obj %erase src/widget/document.obj %erase src/widget/entry.obj %erase src/widget/frame.obj @@ -342,8 +343,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/directx.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/directx.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/d3d8.obj src/widget/d3d9.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/d3d8.obj file src/widget/d3d9.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -499,8 +500,10 @@ src/widget/clock.obj: src/widget/clock.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/clock.c src/widget/combobox.obj: src/widget/combobox.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/combobox.c -src/widget/directx.obj: src/widget/directx.c - $(CC) $(MW_CFLAGS) -fo=$@ src/widget/directx.c +src/widget/d3d8.obj: src/widget/d3d8.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/d3d8.c +src/widget/d3d9.obj: src/widget/d3d9.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/d3d9.c src/widget/document.obj: src/widget/document.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/document.c src/widget/entry.obj: src/widget/entry.c From 5872c43539471fb1bcc9b630c24d871392adbd46 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:11:17 -0700 Subject: [PATCH 144/168] have watcom check for d3d8.h/d3d9.h --- WatMakefile | 16 +++++++++++++++- tools/genmk.pl | 6 ++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/WatMakefile b/WatMakefile index 55bc6b8..02205a7 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,7 +1,20 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECTX8 -dMW_DIRECTX9 +!if [where d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] +!endif +!else +!if [echo DX9_FLAGS =>dx9flags.mk] +!endif +!endif +!if exist("dx9flags.mk") +!include "dx9flags.mk" +!else +DX9_FLAGS = +!endif + +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL $(DX8_FLAGS) $(DX9_FLAGS) MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt @@ -109,6 +122,7 @@ clean: .SYMBOLIC %erase src/widget/window.obj %erase src/Mw.dll %erase src/Mw.lib + %erase dx9flags.mk %erase examples/basic/box.obj %erase examples/basic/calculator.obj %erase examples/basic/checkbox.obj diff --git a/tools/genmk.pl b/tools/genmk.pl index a249e24..9f45add 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -154,8 +154,10 @@ sub generate { $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - $dx8_flags = "${def}MW_DIRECTX8"; - $dx9_flags = "${def}MW_DIRECTX9"; + $dx8_flags = "\$(DX8_FLAGS)"; + $dx8_block = dx8_detect_block(); + $dx9_flags = "\$(DX9_FLAGS)"; + $dx9_block = dx9_detect_block(); } open(OUT, ">", $output); From 2f3b8f2417cb5375611460792c5ac392643a8447 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:16:16 -0700 Subject: [PATCH 145/168] error handling for d3d8 and d3d9 --- src/widget/d3d8.c | 32 +++++++++++++++++++++++++++----- src/widget/d3d9.c | 34 ++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/widget/d3d8.c b/src/widget/d3d8.c index 0663321..d569f53 100644 --- a/src/widget/d3d8.c +++ b/src/widget/d3d8.c @@ -17,21 +17,33 @@ static int wcreate_d3d8(MwWidget handle) { gdid3d8_t* o = malloc(sizeof(gdid3d8_t)); D3DPRESENT_PARAMETERS d3dpp; D3DDISPLAYMODE dispMode; + HRESULT hr; + char errbuf[2048] = {0}; o->d3d8dll = LoadLibrary("d3d8.dll"); if(!o->d3d8dll) { - MessageBox(NULL, "d3d8.dll not found! Is DirectX8 installed?", "Error", MB_OK); - ExitProcess(-1); + MwDispatchError(1, "d3d8.dll not found! Is DirectX8 installed?"); + return 1; } o->Direct3DCreate8 = (void*)GetProcAddress(o->d3d8dll, "Direct3DCreate8"); if(!o->Direct3DCreate8) { - MessageBox(NULL, "Direct3DCreate8 not found! Is DirectX8 installed properly?", "Error", MB_OK); - ExitProcess(-1); + MwDispatchError(1, "Direct3DCreate8 not found! Is DirectX8 installed properly?"); + return 1; } o->d3d = o->Direct3DCreate8(D3D_SDK_VERSION); + if(!o->Direct3DCreate8) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "Direct3DCreate8 NULL: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } - o->d3d->lpVtbl->GetAdapterDisplayMode(o->d3d, D3DADAPTER_DEFAULT, &dispMode); + hr = o->d3d->lpVtbl->GetAdapterDisplayMode(o->d3d, D3DADAPTER_DEFAULT, &dispMode); + if(hr != D3D_OK) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "GetAdapterDisplayMode ERROR: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; @@ -49,8 +61,18 @@ static int wcreate_d3d8(MwWidget handle) { D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &o->d3ddev); + if(hr != D3D_OK) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "CreateDevice ERROR: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } o->d3ddev->lpVtbl->SetRenderState(o->d3ddev, D3DRS_LIGHTING, FALSE); + if(hr != D3D_OK) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "SetRenderState ERROR: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } handle->internal = o; diff --git a/src/widget/d3d9.c b/src/widget/d3d9.c index 3246caf..7219e58 100644 --- a/src/widget/d3d9.c +++ b/src/widget/d3d9.c @@ -12,9 +12,12 @@ typedef struct gdid3d9 { } gdid3d9_t; static int wcreate_d3d9(MwWidget handle) { - void* r = NULL; - MwWidget w = handle; - gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); + void* r = NULL; + MwWidget w = handle; + gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); + HRESULT hr; + char errbuf[2048]; + D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information o->d3d9dll = LoadLibrary("d3d9.dll"); if(!o->d3d9dll) { @@ -24,8 +27,10 @@ static int wcreate_d3d9(MwWidget handle) { o->Direct3DCreate9 = (void*)GetProcAddress(o->d3d9dll, "Direct3DCreate9"); o->d3d = o->Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface - - D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information + if(hr != D3D_OK) { + MwDispatchError(1, "Direct3DCreate9 NULL"); + return 1; + } ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear out the struct for use d3dpp.Windowed = TRUE; // program windowed, not fullscreen @@ -33,13 +38,18 @@ static int wcreate_d3d9(MwWidget handle) { d3dpp.hDeviceWindow = handle->lowlevel->gdi.hWnd; // set the window to be used by Direct3D // create a device class using this information and information from the d3dpp stuct - o->d3d->lpVtbl->CreateDevice(o->d3d, - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - handle->lowlevel->gdi.hWnd, - D3DCREATE_MIXED_VERTEXPROCESSING, - &d3dpp, - &o->d3ddev); + hr = o->d3d->lpVtbl->CreateDevice(o->d3d, + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + handle->lowlevel->gdi.hWnd, + D3DCREATE_MIXED_VERTEXPROCESSING, + &d3dpp, + &o->d3ddev); + if(hr != D3D_OK) { + MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "CreateDevice ERROR: %s", hr); + MwDispatchError(1, errbuf); + return 1; + } handle->internal = o; From f89eaf690139bcbf2aef9d4cd410b1cc829d662f Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:16:43 -0700 Subject: [PATCH 146/168] put nul in gitignore for watcom cross compile --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 3faccd3..ce6459a 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ compile_flags.txt flamegraph.svg perf.* + +nul From a18ca58f1814dc29113c9bb6a2e5942fa09d75f3 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:21:25 -0700 Subject: [PATCH 147/168] xml --- examples/dxdemos/d3d8.c | 4 ++-- examples/dxdemos/d3d9.c | 4 ++-- include/Mw/Widget/D3D8.h | 8 ++++---- include/Mw/Widget/D3D9.h | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/dxdemos/d3d8.c b/examples/dxdemos/d3d8.c index 2ef08a3..c5d65d9 100644 --- a/examples/dxdemos/d3d8.c +++ b/examples/dxdemos/d3d8.c @@ -47,8 +47,8 @@ int main() { d3d8 = MwCreateWidget(MwD3D8Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - d3d = MwDirectXGetD3D8(d3d8); - d3ddev = MwDirectXGetD3Dev8(d3d8); + d3d = MwD3D8GetD3D(d3d8); + d3ddev = MwD3D8GetD3Dev(d3d8); // create three vertices using the CUSTOMVERTEX struct built earlier struct CUSTOMVERTEX vertices[] = diff --git a/examples/dxdemos/d3d9.c b/examples/dxdemos/d3d9.c index 9fe685c..86186ae 100644 --- a/examples/dxdemos/d3d9.c +++ b/examples/dxdemos/d3d9.c @@ -48,8 +48,8 @@ int main() { d3d8 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - d3d = MwDirectXGetD3D9(d3d8); - d3ddev = MwDirectXGetD3Dev9(d3d8); + d3d = MwD3D9GetD3D(d3d8); + d3ddev = MwD3D9GetD3Dev(d3d8); // create three vertices using the CUSTOMVERTEX struct built earlier struct CUSTOMVERTEX vertices[] = diff --git a/include/Mw/Widget/D3D8.h b/include/Mw/Widget/D3D8.h index ee1bf05..9b0ae6e 100644 --- a/include/Mw/Widget/D3D8.h +++ b/include/Mw/Widget/D3D8.h @@ -39,22 +39,22 @@ extern "C" { #endif #ifdef MW_DIRECTX8 -MwInline LPDIRECT3D8 MwDirectXGetD3D8(MwWidget handle) { +MwInline LPDIRECT3D8 MwD3D8GetD3D(MwWidget handle) { LPDIRECT3D8 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3D8", &out, NULL); return out; }; -MwInline LPDIRECT3DDEVICE8 MwDirectXGetD3Dev8(MwWidget handle) { +MwInline LPDIRECT3DDEVICE8 MwD3D8GetD3Dev(MwWidget handle) { LPDIRECT3DDEVICE8 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3Dev8", &out); return out; }; #else -MwInline void* MwDirectXGetD3D8(MwWidget handle) { +MwInline void* MwD3D8GetD3D(MwWidget handle) { (void)handle; return NULL; }; -MwInline void* MwDirectXGetD3Dev8(MwWidget handle) { +MwInline void* MwD3D8GetD3Dev(MwWidget handle) { (void)handle; return NULL; }; diff --git a/include/Mw/Widget/D3D9.h b/include/Mw/Widget/D3D9.h index e7a7149..3831301 100644 --- a/include/Mw/Widget/D3D9.h +++ b/include/Mw/Widget/D3D9.h @@ -38,22 +38,22 @@ extern "C" { #endif #ifdef MW_DIRECTX9 -MwInline LPDIRECT3D9 MwDirectXGetD3D9(MwWidget handle) { +MwInline LPDIRECT3D9 MwD3D9GetD3D(MwWidget handle) { LPDIRECT3D9 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3D9", &out, NULL); return out; }; -MwInline LPDIRECT3DDEVICE9 MwDirectXGetD3Dev9(MwWidget handle) { +MwInline LPDIRECT3DDEVICE9 MwD3D9GetD3Dev(MwWidget handle) { LPDIRECT3DDEVICE9 out = NULL; MwVaWidgetExecute(handle, "mwDirectXGetD3Dev9", &out); return out; }; #else -MwInline void* MwDirectXGetD3D9(MwWidget handle) { +MwInline void* MwD3D9GetD3D(MwWidget handle) { (void)handle; return NULL; }; -MwInline void* MwDirectXGetD3Dev9(MwWidget handle) { +MwInline void* MwD3D9GetD3Dev(MwWidget handle) { (void)handle; return NULL; }; From fb9919de2a90b87a01a279a999a854d1ab4beef4 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 17 Sep 2026 22:24:48 -0700 Subject: [PATCH 148/168] oh wait the jenkinsfile can at least use enable-d3d --- Jenkinsfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6d93874..c688af0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,7 +30,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-directx --enable-vulkan --without-vulkan-string-helper") + sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --enable-vulkan --without-vulkan-string-helper") sh("make -j4") sh("mv src/libMw.so libMw64.so") archiveArtifacts("libMw64.so") @@ -42,7 +42,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-directx --cross --target=Windows --host=i686-w64-mingw32") + sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --cross --target=Windows --host=i686-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw32.dll") sh("mv src/libMw.dll.a libMw32.dll.a") @@ -55,7 +55,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-directx --cross --target=Windows --host=x86_64-w64-mingw32") + sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --cross --target=Windows --host=x86_64-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw64.dll") sh("mv src/libMw.dll.a libMw64.dll.a") From a0da41210a37ef1894715191bf3a95ab20a933f9 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 18 Sep 2026 15:42:10 +0900 Subject: [PATCH 149/168] Update configure --- configure | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/configure b/configure index a2d0ba6..c4fc7e9 100755 --- a/configure +++ b/configure @@ -54,10 +54,6 @@ param_set("examples", 1); # (option that only makes sense on x11) param_set("allow-sloppy-focus", 0); -# (option that only makes sense on Windows) -param_set("dxd8", 0); -param_set("dxd9", 0); - my %features = ( "classic-theme" => "use classic theme", "stb-image" => "use stb_image, instead use libjpeg/libpng", @@ -91,6 +87,8 @@ sub def_platform { if($target eq "Windows") { param_set("freetype2", 0); param_set("stb-truetype", 0); + param_set("dxd8", 1); + param_set("dxd9", 1); } elsif($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Haiku") { param_set("freetype2", 1); param_set("stb-truetype", 0); From aef5fe03a972e8ef7725d391f4cc273d2c5200ee Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 18 Sep 2026 15:45:38 +0900 Subject: [PATCH 150/168] Update configure --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index c4fc7e9..5463444 100755 --- a/configure +++ b/configure @@ -87,8 +87,8 @@ sub def_platform { if($target eq "Windows") { param_set("freetype2", 0); param_set("stb-truetype", 0); - param_set("dxd8", 1); - param_set("dxd9", 1); + param_set("d3d8", 1); + param_set("d3d9", 1); } elsif($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Haiku") { param_set("freetype2", 1); param_set("stb-truetype", 0); From e967523063f21726693ec780ddc94def22412090 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 18 Sep 2026 15:46:57 +0900 Subject: [PATCH 151/168] Update pl/rules.pl --- pl/rules.pl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pl/rules.pl b/pl/rules.pl index 76ab9b4..2c1cd24 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -187,10 +187,10 @@ if (param_get("opengl")) { if (param_get("vulkan")) { add_cflags("-DMW_VULKAN"); } -if (param_get("directx8")) { +if (param_get("d3d8")) { add_cflags("-DMW_DIRECTX8"); } -if (param_get("directx9")) { +if (param_get("d3d9")) { add_cflags("-DMW_DIRECTX9"); } @@ -238,11 +238,11 @@ if (param_get("vulkan")) { new_example("examples/vkdemos/vulkan"); } -if (param_get("directx8")) { +if (param_get("d3d8")) { new_example("examples/dxdemos/d3d8"); } -if (param_get("directx9")) { +if (param_get("d3d9")) { new_example("examples/dxdemos/d3d9"); } From 12b89aab9b596cd340ca2822893c04795710f537 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 18 Sep 2026 15:49:44 +0900 Subject: [PATCH 152/168] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index c688af0..c506028 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,7 +30,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --enable-vulkan --without-vulkan-string-helper") + sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper") sh("make -j4") sh("mv src/libMw.so libMw64.so") archiveArtifacts("libMw64.so") From c5330cc18419f2650050c325bf312522f4fd5228 Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 16:43:15 +0900 Subject: [PATCH 153/168] direct3d9 --- CMakeLists.txt | 29 ++--- NTMakefile | 2 +- WatMakefile | 2 +- configure | 8 +- examples/CMakeLists.txt | 2 +- examples/dxdemos/d3d8.c | 95 ---------------- examples/dxdemos/{d3d9.c => direct3d9.c} | 27 ++--- include/Mw/Widget/D3D8.h | 67 ------------ include/Mw/Widget/{D3D9.h => Direct3D9.h} | 34 ++---- pl/rules.pl | 18 +-- src/widget/d3d8.c | 127 ---------------------- src/widget/{d3d9.c => direct3d9.c} | 59 +++++----- tools/genmk.pl | 30 +---- 13 files changed, 74 insertions(+), 426 deletions(-) delete mode 100644 examples/dxdemos/d3d8.c rename examples/dxdemos/{d3d9.c => direct3d9.c} (90%) delete mode 100644 include/Mw/Widget/D3D8.h rename include/Mw/Widget/{D3D9.h => Direct3D9.h} (53%) delete mode 100644 src/widget/d3d8.c rename src/widget/{d3d9.c => direct3d9.c} (65%) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa1644d..15cbb11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,9 @@ else() endif() if(${CMAKE_SYSTEM_NAME} MATCHES Windows) - option(MW_TRY_D3D8 "Try to compile D3D8 widget or not" ON) - option(MW_TRY_D3D9 "Try to compile D3D9 widget or not" ON) + option(MW_TRY_DIRECT3D9 "Try to compile Direct3D9 widget or not" ON) +else() + option(MW_TRY_DIRECT3D9 "Try to compile Direct3D9 widget or not" OFF) endif() @@ -96,16 +97,12 @@ if(MW_TRY_VULKAN) endif() endif() -if(MW_TRY_D3D8 OR MW_TRY_D3D9) +if(MW_TRY_DIRECT3D9) include(${CMAKE_CURRENT_SOURCE_DIR}/resource/FindDirectX.cmake) if(DIRECTX_FOUND) - if(MW_TRY_D3D8) - set(MW_BUILD_D3D8 ON) - message(STATUS "D3D8 widget has been enabled") - endif() - if(MW_TRY_D3D9) - set(MW_BUILD_D3D9 ON) - message(STATUS "D3D9 widget has been enabled") + if(MW_TRY_DIRECT3D9) + set(MW_BUILD_DIRECT3D9 ON) + message(STATUS "Direct3D9 widget has been enabled") endif() else() message(STATUS "DirectX widgets have been disabled (DirectX not found)") @@ -499,19 +496,11 @@ if(MW_BUILD_VULKAN) endif() endif() -if(MW_BUILD_D3D8) +if(MW_BUILD_DIRECT3D9) target_compile_definitions( Mw PUBLIC - MW_DIRECTX8 - ) -endif() - -if(MW_BUILD_D3D9) - target_compile_definitions( - Mw - PUBLIC - MW_DIRECTX9 + MW_DIRECT3D9 ) endif() diff --git a/NTMakefile b/NTMakefile index f42873b..a549015 100644 --- a/NTMakefile +++ b/NTMakefile @@ -14,7 +14,7 @@ LD = link /nologo DX9_FLAGS = !endif -MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX8_FLAGS) $(DX9_FLAGS) +MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT /DMW_OPENGL $(DX9_FLAGS) MW_LDFLAGS = /DLL EXE_CFLAGS = /Iinclude EXE_LDFLAGS = diff --git a/WatMakefile b/WatMakefile index 02205a7..99334e5 100644 --- a/WatMakefile +++ b/WatMakefile @@ -14,7 +14,7 @@ LD = wlink option quiet DX9_FLAGS = !endif -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL $(DX8_FLAGS) $(DX9_FLAGS) +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL $(DX9_FLAGS) MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt diff --git a/configure b/configure index 5463444..025b265 100755 --- a/configure +++ b/configure @@ -70,8 +70,7 @@ my %features = ( "gnustep" => "use gnustep", "dbus" => "use DBus on supported platform", "allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus", - "directx8" => "(Windows only) build DXD8 widget", - "directx9" => "(Windows only) build DXD9 widget" + "direct3d9" => "(Windows only) build Direct3D9 widget" ); my @features_keys = ( "1classic-theme", "1stb-image", @@ -80,15 +79,14 @@ my @features_keys = ( "1vulkan", "2vulkan-string-helper", "1shared", "1static", "1wayland", "1gnustep", - "1dbus", "1direct8", "1directx9" + "1dbus", "1direct3d9" ); sub def_platform { if($target eq "Windows") { param_set("freetype2", 0); param_set("stb-truetype", 0); - param_set("d3d8", 1); - param_set("d3d9", 1); + param_set("direct3d9", 1); } elsif($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Haiku") { param_set("freetype2", 1); param_set("stb-truetype", 0); diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 87225f1..821516f 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -7,7 +7,7 @@ if(${MW_TRY_VULKAN}) endif() if(WIN32) - if(${MW_TRY_D3D8} OR ${MW_BUILD_D3D8}) + if(${MW_TRY_DIRECT3D9}) add_subdirectory(dxdemos) endif() endif() diff --git a/examples/dxdemos/d3d8.c b/examples/dxdemos/d3d8.c deleted file mode 100644 index c5d65d9..0000000 --- a/examples/dxdemos/d3d8.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Adapted from: - * https://web.archive.org/web/20211126225651/https://www.codeguru.com/multimedia/using-direct3d8-the-basics/ - */ -#include -#include - -#ifdef MW_DIRECTX8 - -MwWidget window, d3d8; -LPDIRECT3D8 d3d; -LPDIRECT3DDEVICE8 d3ddev; -LPDIRECT3DVERTEXBUFFER8 v_buffer; - -struct CUSTOMVERTEX { - FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag - DWORD color; // from the D3DFVF_DIFFUSE flag -}; -#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) - -static void MWAPI draw(MwWidget handle, void* user, void* client) { - // clear the window to a deep blue - d3ddev->lpVtbl->Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); - - d3ddev->lpVtbl->BeginScene(d3ddev); // begins the 3D scene - - // select which vertex format we are using - d3ddev->lpVtbl->SetVertexShader(d3ddev, CUSTOMFVF); - - // select the vertex buffer to display - d3ddev->lpVtbl->SetStreamSource(d3ddev, 0, v_buffer, sizeof(struct CUSTOMVERTEX)); - - // // copy the vertex buffer to the back buffer - d3ddev->lpVtbl->DrawPrimitive(d3ddev, D3DPT_TRIANGLELIST, 0, 1); - - d3ddev->lpVtbl->EndScene(d3ddev); // ends the 3D scene - - d3ddev->lpVtbl->Present(d3ddev, NULL, NULL, NULL, NULL); // displays the created frame -} - -int main() { - BYTE* pVoid; - - MwLibraryInit(); - - window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); - - d3d8 = MwCreateWidget(MwD3D8Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - - d3d = MwD3D8GetD3D(d3d8); - d3ddev = MwD3D8GetD3Dev(d3d8); - - // create three vertices using the CUSTOMVERTEX struct built earlier - struct CUSTOMVERTEX vertices[] = - { - { - 400.0f, - 0.0f, - 0.5f, - 1.0f, - D3DCOLOR_XRGB(0, 0, 255), - }, - { - 800.0f, - 600.0f, - 0.5f, - 1.0f, - D3DCOLOR_XRGB(0, 255, 0), - }, - { - 0.0f, - 600.0f, - 0.5f, - 1.0f, - D3DCOLOR_XRGB(255, 0, 0), - }, - }; - - d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, - 3 * sizeof(struct CUSTOMVERTEX), - 0, - CUSTOMFVF, - D3DPOOL_MANAGED, - &v_buffer); - - v_buffer->lpVtbl->Lock(v_buffer, 0, 0, (BYTE**)&pVoid, 0); // lock the vertex buffer - memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer - v_buffer->lpVtbl->Unlock(v_buffer); // unlock the vertex buffer - - MwAddUserHandler(window, MwNtickHandler, draw, NULL); - - MwLoop(window); -} - -#endif diff --git a/examples/dxdemos/d3d9.c b/examples/dxdemos/direct3d9.c similarity index 90% rename from examples/dxdemos/d3d9.c rename to examples/dxdemos/direct3d9.c index 86186ae..47a2609 100644 --- a/examples/dxdemos/d3d9.c +++ b/examples/dxdemos/direct3d9.c @@ -4,11 +4,9 @@ * http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-4 */ #include -#include +#include -#ifdef MW_DIRECTX9 - -MwWidget window, d3d8; +MwWidget window, d3d9; LPDIRECT3D9 d3d; LPDIRECT3DDEVICE9 d3ddev; LPDIRECT3DVERTEXBUFFER9 v_buffer; @@ -41,16 +39,6 @@ static void MWAPI draw(MwWidget handle, void* user, void* client) { int main() { VOID* pVoid; - - MwLibraryInit(); - - window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); - - d3d8 = MwCreateWidget(MwD3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - - d3d = MwD3D9GetD3D(d3d8); - d3ddev = MwD3D9GetD3Dev(d3d8); - // create three vertices using the CUSTOMVERTEX struct built earlier struct CUSTOMVERTEX vertices[] = { @@ -77,6 +65,15 @@ int main() { }, }; + MwLibraryInit(); + + window = MwCreateWidget(MwWindowClass, NULL, NULL, MwDEFAULT, MwDEFAULT, 1024, 768); + + d3d9 = MwCreateWidget(MwDirect3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); + + d3d = MwDirect3D9GetD3D(d3d9); + d3ddev = MwDirect3D9GetD3DDevice(d3d9); + d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, 3 * sizeof(struct CUSTOMVERTEX), 0, @@ -93,5 +90,3 @@ int main() { MwLoop(window); } - -#endif diff --git a/include/Mw/Widget/D3D8.h b/include/Mw/Widget/D3D8.h deleted file mode 100644 index 9b0ae6e..0000000 --- a/include/Mw/Widget/D3D8.h +++ /dev/null @@ -1,67 +0,0 @@ -/*! - * @file Mw/Widget/D3D8.h - * @brief D3D8 widget. - * @warning Only avaliable on Windows. - */ -#ifndef __MW_WIDGET_D3D8_H__ -#define __MW_WIDGET_D3D8_H__ - -#include -#include -#include - -#if !defined(MW_D3D8_NO_INCLUDE) - -/* https://github.com/microsoft/Windows-classic-samples/issues/317 */ -#if defined(__MINGW32__) || defined(__MINGW64__) -#define NTDDI_VERSION 0x07000000 -#define _WIN32_WINNT 0x0A00 - -#endif -#endif - -#ifndef _WIN32 -#error D3D8 widget only avaliable for Win32 backends -#undef MW_DIRECTX8 -#else -#ifdef MW_DIRECTX8 -#include -#endif -#endif - -/*! - * @brief D3D8 widget class - */ -MWDECL MwClass MwD3D8Class; - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef MW_DIRECTX8 -MwInline LPDIRECT3D8 MwD3D8GetD3D(MwWidget handle) { - LPDIRECT3D8 out = NULL; - MwVaWidgetExecute(handle, "mwDirectXGetD3D8", &out, NULL); - return out; -}; -MwInline LPDIRECT3DDEVICE8 MwD3D8GetD3Dev(MwWidget handle) { - LPDIRECT3DDEVICE8 out = NULL; - MwVaWidgetExecute(handle, "mwDirectXGetD3Dev8", &out); - return out; -}; -#else -MwInline void* MwD3D8GetD3D(MwWidget handle) { - (void)handle; - return NULL; -}; -MwInline void* MwD3D8GetD3Dev(MwWidget handle) { - (void)handle; - return NULL; -}; -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/Mw/Widget/D3D9.h b/include/Mw/Widget/Direct3D9.h similarity index 53% rename from include/Mw/Widget/D3D9.h rename to include/Mw/Widget/Direct3D9.h index 3831301..f31e247 100644 --- a/include/Mw/Widget/D3D9.h +++ b/include/Mw/Widget/Direct3D9.h @@ -3,61 +3,51 @@ * @brief DirectX widget. * @warning Only avaliable on Windows. */ -#ifndef __MW_WIDGET_D3D9_H__ -#define __MW_WIDGET_D3D9_H__ +#ifndef __MW_WIDGET_DIRECT3D9_H__ +#define __MW_WIDGET_DIRECT3D9_H__ #include #include #include -#if !defined(MW_D3D9_NO_INCLUDE) +#if !defined(MW_DIRECT3D9_NO_INCLUDE) /* https://github.com/microsoft/Windows-classic-samples/issues/317 */ #if defined(__MINGW32__) || defined(__MINGW64__) +#undef NTDDI_VERSION +#undef _WIN32_WINNT + #define NTDDI_VERSION 0x07000000 #define _WIN32_WINNT 0x0A00 #endif #ifndef _WIN32 #error D3D9 widget only avaliable for Win32 backends -#undef MW_DIRECTX9 +#undef MW_DIRECT3D9 #else -#ifdef MW_DIRECTX9 #include #endif #endif -#endif /*! * @brief D3D9 widget class */ -MWDECL MwClass MwD3D9Class; +MWDECL MwClass MwDirect3D9Class; #ifdef __cplusplus extern "C" { #endif -#ifdef MW_DIRECTX9 -MwInline LPDIRECT3D9 MwD3D9GetD3D(MwWidget handle) { +MwInline LPDIRECT3D9 MwDirect3D9GetD3D(MwWidget handle) { LPDIRECT3D9 out = NULL; - MwVaWidgetExecute(handle, "mwDirectXGetD3D9", &out, NULL); + MwVaWidgetExecute(handle, "mwDirect3D9GetD3D9", &out, NULL); return out; }; -MwInline LPDIRECT3DDEVICE9 MwD3D9GetD3Dev(MwWidget handle) { +MwInline LPDIRECT3DDEVICE9 MwDirect3D9GetD3DDevice(MwWidget handle) { LPDIRECT3DDEVICE9 out = NULL; - MwVaWidgetExecute(handle, "mwDirectXGetD3Dev9", &out); + MwVaWidgetExecute(handle, "mwDirect3D9GetD3DDevice9", &out); return out; }; -#else -MwInline void* MwD3D9GetD3D(MwWidget handle) { - (void)handle; - return NULL; -}; -MwInline void* MwD3D9GetD3Dev(MwWidget handle) { - (void)handle; - return NULL; -}; -#endif #ifdef __cplusplus } diff --git a/pl/rules.pl b/pl/rules.pl index 2c1cd24..276eb88 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -178,8 +178,7 @@ new_object("src/widget/window.c"); new_object("src/widget/opengl.c"); new_object("src/widget/vulkan.c"); -new_object("src/widget/d3d8.c"); -new_object("src/widget/d3d9.c"); +new_object("src/widget/direct3d9.c"); if (param_get("opengl")) { add_cflags("-DMW_OPENGL"); @@ -187,11 +186,8 @@ if (param_get("opengl")) { if (param_get("vulkan")) { add_cflags("-DMW_VULKAN"); } -if (param_get("d3d8")) { - add_cflags("-DMW_DIRECTX8"); -} -if (param_get("d3d9")) { - add_cflags("-DMW_DIRECTX9"); +if (param_get("direct3d9")) { + add_cflags("-DMW_DIRECT3D9"); } new_object("src/dialog/*.c"); @@ -238,12 +234,8 @@ if (param_get("vulkan")) { new_example("examples/vkdemos/vulkan"); } -if (param_get("d3d8")) { - new_example("examples/dxdemos/d3d8"); -} - -if (param_get("d3d9")) { - new_example("examples/dxdemos/d3d9"); +if (param_get("direct3d9")) { + new_example("examples/dxdemos/direct3d9"); } 1; diff --git a/src/widget/d3d8.c b/src/widget/d3d8.c deleted file mode 100644 index d569f53..0000000 --- a/src/widget/d3d8.c +++ /dev/null @@ -1,127 +0,0 @@ -#include - -#ifdef MW_DIRECTX8 -#include -typedef struct gdid3d8 { - void* d3d8dll; - IDirect3D8* (*Direct3DCreate8)(UINT sdk_version); - - LPDIRECT3D8 d3d; // the pointer to our Direct3D interface - LPDIRECT3DDEVICE8 d3ddev; // the pointer to the device class\ - -} gdid3d8_t; - -static int wcreate_d3d8(MwWidget handle) { - void* r = NULL; - MwWidget w = handle; - gdid3d8_t* o = malloc(sizeof(gdid3d8_t)); - D3DPRESENT_PARAMETERS d3dpp; - D3DDISPLAYMODE dispMode; - HRESULT hr; - char errbuf[2048] = {0}; - - o->d3d8dll = LoadLibrary("d3d8.dll"); - if(!o->d3d8dll) { - MwDispatchError(1, "d3d8.dll not found! Is DirectX8 installed?"); - return 1; - } - o->Direct3DCreate8 = (void*)GetProcAddress(o->d3d8dll, "Direct3DCreate8"); - if(!o->Direct3DCreate8) { - MwDispatchError(1, "Direct3DCreate8 not found! Is DirectX8 installed properly?"); - return 1; - } - - o->d3d = o->Direct3DCreate8(D3D_SDK_VERSION); - if(!o->Direct3DCreate8) { - MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "Direct3DCreate8 NULL: %s", hr); - MwDispatchError(1, errbuf); - return 1; - } - - hr = o->d3d->lpVtbl->GetAdapterDisplayMode(o->d3d, D3DADAPTER_DEFAULT, &dispMode); - if(hr != D3D_OK) { - MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "GetAdapterDisplayMode ERROR: %s", hr); - MwDispatchError(1, errbuf); - return 1; - } - - ZeroMemory(&d3dpp, sizeof(d3dpp)); - d3dpp.Windowed = TRUE; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.hDeviceWindow = handle->lowlevel->gdi.hWnd; - d3dpp.BackBufferFormat = dispMode.Format; - d3dpp.EnableAutoDepthStencil = TRUE; - d3dpp.AutoDepthStencilFormat = D3DFMT_D16; - - // create a device class using this information and information from the d3dpp stuct - o->d3d->lpVtbl->CreateDevice(o->d3d, - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - handle->lowlevel->gdi.hWnd, - D3DCREATE_MIXED_VERTEXPROCESSING, - &d3dpp, - &o->d3ddev); - if(hr != D3D_OK) { - MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "CreateDevice ERROR: %s", hr); - MwDispatchError(1, errbuf); - return 1; - } - - o->d3ddev->lpVtbl->SetRenderState(o->d3ddev, D3DRS_LIGHTING, FALSE); - if(hr != D3D_OK) { - MwStringPrintIntoBuffer(errbuf, sizeof(errbuf) - 1, "SetRenderState ERROR: %s", hr); - MwDispatchError(1, errbuf); - return 1; - } - - handle->internal = o; - - return 0; -} - -static void destroy_d3d8(MwWidget handle) { - MwWidget w = handle; - gdid3d8_t* o = handle->internal; - - o->d3ddev->lpVtbl->Release(o->d3ddev); // close and release the 3D device - o->d3d->lpVtbl->Release(o->d3d); // close and release Direct3D - - free(handle->internal); -} - -static void func_handler_d3d8(MwWidget handle, const char* name, void* out, - va_list va) { - gdid3d8_t* o = handle->internal; - - if(strcmp(name, "mwDirectXGetD3D8") == 0) { - *(LPDIRECT3D8*)out = o->d3d; - } - if(strcmp(name, "mwDirectXGetD3Dev8") == 0) { - *(LPDIRECT3DDEVICE8*)out = o->d3ddev; - } -} - -MwClassRec MwDX8ClassRec = {wcreate_d3d8, /* create */ - destroy_d3d8, /* destroy */ - NULL, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - NULL, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler_d3d8, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ - NULL, NULL, NULL}; -MwClass MwD3D8Class = &MwDX8ClassRec; -#else -MWDECL MwClass MwDX8Class; - -MwClass MwDX8Class = NULL; -#endif diff --git a/src/widget/d3d9.c b/src/widget/direct3d9.c similarity index 65% rename from src/widget/d3d9.c rename to src/widget/direct3d9.c index 7219e58..da77041 100644 --- a/src/widget/d3d9.c +++ b/src/widget/direct3d9.c @@ -1,19 +1,17 @@ #include -#ifdef MW_DIRECTX9 -#include +#ifdef MW_DIRECT3D9 +#include typedef struct gdid3d9 { void* d3d9dll; IDirect3D9* (*Direct3DCreate9)(UINT sdk_version); LPDIRECT3D9 d3d; // the pointer to our Direct3D interface - LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class\ + LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class } gdid3d9_t; static int wcreate_d3d9(MwWidget handle) { - void* r = NULL; - MwWidget w = handle; gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); HRESULT hr; char errbuf[2048]; @@ -27,7 +25,7 @@ static int wcreate_d3d9(MwWidget handle) { o->Direct3DCreate9 = (void*)GetProcAddress(o->d3d9dll, "Direct3DCreate9"); o->d3d = o->Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface - if(hr != D3D_OK) { + if(o->d3d == NULL) { MwDispatchError(1, "Direct3DCreate9 NULL"); return 1; } @@ -57,7 +55,6 @@ static int wcreate_d3d9(MwWidget handle) { } static void destroy_d3d9(MwWidget handle) { - MwWidget w = handle; gdid3d9_t* o = handle->internal; o->d3ddev->lpVtbl->Release(o->d3ddev); // close and release the 3D device @@ -70,35 +67,35 @@ static void func_handler_d3d9(MwWidget handle, const char* name, void* out, va_list va) { gdid3d9_t* o = handle->internal; - if(strcmp(name, "mwDirectXGetD3D9") == 0) { + (void)va; + + if(strcmp(name, "mwDirect3D9GetD3D9") == 0) { *(LPDIRECT3D9*)out = o->d3d; } - if(strcmp(name, "mwDirectXGetD3Dev9") == 0) { + if(strcmp(name, "mwDirect3D9GetD3DDevice9") == 0) { *(LPDIRECT3DDEVICE9*)out = o->d3ddev; } } -MwClassRec MwDX9ClassRec = {wcreate_d3d9, /* create */ - destroy_d3d9, /* destroy */ - NULL, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - NULL, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler_d3d9, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ - NULL, NULL, NULL}; -MwClass MwD3D9Class = &MwDX9ClassRec; +MwClassRec MwDirect3D9ClassRec = {wcreate_d3d9, /* create */ + destroy_d3d9, /* destroy */ + NULL, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + NULL, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler_d3d9, /* execute */ + NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ + NULL, NULL, NULL}; +MwClass MwDirect3D9Class = &MwDirect3D9ClassRec; #else -MWDECL MwClass MwDX9Class; - -MwClass MwDX9Class = NULL; +MwClass MwDirect3D9Class = NULL; #endif diff --git a/tools/genmk.pl b/tools/genmk.pl index 9f45add..369ed58 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -42,24 +42,6 @@ sub cobjs { return $r; } - -sub dx8_detect_block { - return <<'EOF'; -!if [where d3d8.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d8.h 2^>nul') do @echo DX8_FLAGS = /DMW_DIRECTX8 /I"%~dpP">dx8flags.mk] -!endif -!else -!if [echo DX8_FLAGS =>dx9flags.mk] -!endif -!endif -!if exist("dx8flags.mk") -!include "dx8flags.mk" -!else -DX8_FLAGS = -!endif -EOF -} - sub dx9_detect_block { return <<'EOF'; !if [where d3d9.h >nul 2>nul] @@ -100,10 +82,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; - my $dx8_flags = ""; - my $dx8_block = ""; - my $dx9_flags = ""; - my $dx9_block = ""; + my $dx9_flags = ""; + my $dx9_block = ""; if ($type eq "Borland") { $cc = "bcc32 -c"; @@ -128,8 +108,6 @@ sub generate { $inc = "/I"; $dll = "/DLL"; - $dx8_flags = "\$(DX8_FLAGS)"; - $dx8_block = dx8_detect_block(); $dx9_flags = "\$(DX9_FLAGS)"; $dx9_block = dx9_detect_block(); } @@ -154,8 +132,6 @@ sub generate { $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - $dx8_flags = "\$(DX8_FLAGS)"; - $dx8_block = dx8_detect_block(); $dx9_flags = "\$(DX9_FLAGS)"; $dx9_block = dx9_detect_block(); } @@ -169,7 +145,7 @@ sub generate { print(OUT "\n"); } print(OUT -"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx8_flags} ${dx9_flags}\n" +"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx9_flags}\n" ); print(OUT "MW_LDFLAGS = $dll\n"); print(OUT "EXE_CFLAGS = ${inc}include\n"); From 83eb8c8dc4291c5529e8654e857c230e53a5c0cf Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 16:43:56 +0900 Subject: [PATCH 154/168] ok --- NTMakefile | 9 ++++----- WatMakefile | 15 ++++++--------- tools/genmk.pl | 2 +- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/NTMakefile b/NTMakefile index a549015..9f8ffe7 100644 --- a/NTMakefile +++ b/NTMakefile @@ -2,7 +2,7 @@ CC = cl /TC /c /nologo LD = link /nologo !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] @@ -99,8 +99,7 @@ clean: del /f /q src\widget\checkbox.obj del /f /q src\widget\clock.obj del /f /q src\widget\combobox.obj - del /f /q src\widget\d3d8.obj - del /f /q src\widget\d3d9.obj + del /f /q src\widget\direct3d9.obj del /f /q src\widget\document.obj del /f /q src\widget\entry.obj del /f /q src\widget\frame.obj @@ -358,8 +357,8 @@ examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c -src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\d3d8.obj src\widget\d3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\d3d8.obj src\widget\d3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib +src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\direct3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\md4c.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\center.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hand.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\chart.obj src\widget\checkbox.obj src\widget\clock.obj src\widget\combobox.obj src\widget\direct3d9.obj src\widget\document.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib ole32.lib uuid.lib user32.lib advapi32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index 99334e5..f8cc430 100644 --- a/WatMakefile +++ b/WatMakefile @@ -2,7 +2,7 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] @@ -98,8 +98,7 @@ clean: .SYMBOLIC %erase src/widget/checkbox.obj %erase src/widget/clock.obj %erase src/widget/combobox.obj - %erase src/widget/d3d8.obj - %erase src/widget/d3d9.obj + %erase src/widget/direct3d9.obj %erase src/widget/document.obj %erase src/widget/entry.obj %erase src/widget/frame.obj @@ -357,8 +356,8 @@ examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c -src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/d3d8.obj src/widget/d3d9.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/d3d8.obj file src/widget/d3d9.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib +src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/md4c.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/center.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hand.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/chart.obj src/widget/checkbox.obj src/widget/clock.obj src/widget/combobox.obj src/widget/direct3d9.obj src/widget/document.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/md4c.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/center.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hand.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/chart.obj file src/widget/checkbox.obj file src/widget/clock.obj file src/widget/combobox.obj file src/widget/direct3d9.obj file src/widget/document.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library ole32.lib library uuid.lib library user32.lib library advapi32.lib @@ -514,10 +513,8 @@ src/widget/clock.obj: src/widget/clock.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/clock.c src/widget/combobox.obj: src/widget/combobox.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/combobox.c -src/widget/d3d8.obj: src/widget/d3d8.c - $(CC) $(MW_CFLAGS) -fo=$@ src/widget/d3d8.c -src/widget/d3d9.obj: src/widget/d3d9.c - $(CC) $(MW_CFLAGS) -fo=$@ src/widget/d3d9.c +src/widget/direct3d9.obj: src/widget/direct3d9.c + $(CC) $(MW_CFLAGS) -fo=$@ src/widget/direct3d9.c src/widget/document.obj: src/widget/document.c $(CC) $(MW_CFLAGS) -fo=$@ src/widget/document.c src/widget/entry.obj: src/widget/entry.c diff --git a/tools/genmk.pl b/tools/genmk.pl index 369ed58..9529770 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -45,7 +45,7 @@ sub cobjs { sub dx9_detect_block { return <<'EOF'; !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECTX9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] !endif !else !if [echo DX9_FLAGS =>dx9flags.mk] From ec45c8828d8d6a7b6d42ce4e039149436cac5158 Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 16:47:13 +0900 Subject: [PATCH 155/168] rename --- examples/dxdemos/direct3d9.c | 4 ++-- include/Mw/Widget/Direct3D9.h | 8 ++++---- src/widget/direct3d9.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/dxdemos/direct3d9.c b/examples/dxdemos/direct3d9.c index 47a2609..368d618 100644 --- a/examples/dxdemos/direct3d9.c +++ b/examples/dxdemos/direct3d9.c @@ -71,8 +71,8 @@ int main() { d3d9 = MwCreateWidget(MwDirect3D9Class, NULL, window, (1024 - 800) / 2, (768 - 600) / 2, 800, 600); - d3d = MwDirect3D9GetD3D(d3d9); - d3ddev = MwDirect3D9GetD3DDevice(d3d9); + d3d = MwDirect3D9GetDirect3D9(d3d9); + d3ddev = MwDirect3D9GetDirect3DDevice9(d3d9); d3ddev->lpVtbl->CreateVertexBuffer(d3ddev, 3 * sizeof(struct CUSTOMVERTEX), diff --git a/include/Mw/Widget/Direct3D9.h b/include/Mw/Widget/Direct3D9.h index f31e247..b6904d4 100644 --- a/include/Mw/Widget/Direct3D9.h +++ b/include/Mw/Widget/Direct3D9.h @@ -38,14 +38,14 @@ MWDECL MwClass MwDirect3D9Class; extern "C" { #endif -MwInline LPDIRECT3D9 MwDirect3D9GetD3D(MwWidget handle) { +MwInline LPDIRECT3D9 MwDirect3D9GetDirect3D9(MwWidget handle) { LPDIRECT3D9 out = NULL; - MwVaWidgetExecute(handle, "mwDirect3D9GetD3D9", &out, NULL); + MwVaWidgetExecute(handle, "mwDirect3D9GetDirect3D9", &out, NULL); return out; }; -MwInline LPDIRECT3DDEVICE9 MwDirect3D9GetD3DDevice(MwWidget handle) { +MwInline LPDIRECT3DDEVICE9 MwDirect3D9GetDirect3DDevice9(MwWidget handle) { LPDIRECT3DDEVICE9 out = NULL; - MwVaWidgetExecute(handle, "mwDirect3D9GetD3DDevice9", &out); + MwVaWidgetExecute(handle, "mwDirect3D9GetDirect3DDevice9", &out); return out; }; diff --git a/src/widget/direct3d9.c b/src/widget/direct3d9.c index da77041..4134786 100644 --- a/src/widget/direct3d9.c +++ b/src/widget/direct3d9.c @@ -69,10 +69,10 @@ static void func_handler_d3d9(MwWidget handle, const char* name, void* out, (void)va; - if(strcmp(name, "mwDirect3D9GetD3D9") == 0) { + if(strcmp(name, "mwDirect3D9GetDirect3D9") == 0) { *(LPDIRECT3D9*)out = o->d3d; } - if(strcmp(name, "mwDirect3D9GetD3DDevice9") == 0) { + if(strcmp(name, "mwDirect3D9GetDirect3DDevice9") == 0) { *(LPDIRECT3DDEVICE9*)out = o->d3ddev; } } From 7f361b9d15919e07c4186d7e231b315977543b7f Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 18 Sep 2026 16:49:06 +0900 Subject: [PATCH 156/168] correct names --- NTMakefile | 10 +++++----- WatMakefile | 10 +++++----- tools/genmk.pl | 32 ++++++++++++++++---------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/NTMakefile b/NTMakefile index 9f8ffe7..0383974 100644 --- a/NTMakefile +++ b/NTMakefile @@ -2,14 +2,14 @@ CC = cl /TC /c /nologo LD = link /nologo !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else -!if [echo DX9_FLAGS =>dx9flags.mk] +!if [echo DX9_FLAGS =>d3d9flags.mk] !endif !endif -!if exist("dx9flags.mk") -!include "dx9flags.mk" +!if exist("d3d9flags.mk") +!include "d3d9flags.mk" !else DX9_FLAGS = !endif @@ -122,7 +122,7 @@ clean: del /f /q src\widget\window.obj del /f /q src\Mw.dll del /f /q src\Mw.lib - del /f /q dx9flags.mk + del /f /q d3d9flags.mk del /f /q examples\basic\box.obj del /f /q examples\basic\calculator.obj del /f /q examples\basic\checkbox.obj diff --git a/WatMakefile b/WatMakefile index f8cc430..0702947 100644 --- a/WatMakefile +++ b/WatMakefile @@ -2,14 +2,14 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else -!if [echo DX9_FLAGS =>dx9flags.mk] +!if [echo DX9_FLAGS =>d3d9flags.mk] !endif !endif -!if exist("dx9flags.mk") -!include "dx9flags.mk" +!if exist("d3d9flags.mk") +!include "d3d9flags.mk" !else DX9_FLAGS = !endif @@ -121,7 +121,7 @@ clean: .SYMBOLIC %erase src/widget/window.obj %erase src/Mw.dll %erase src/Mw.lib - %erase dx9flags.mk + %erase d3d9flags.mk %erase examples/basic/box.obj %erase examples/basic/calculator.obj %erase examples/basic/checkbox.obj diff --git a/tools/genmk.pl b/tools/genmk.pl index 9529770..e8c7695 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -42,17 +42,17 @@ sub cobjs { return $r; } -sub dx9_detect_block { +sub d3d9_detect_block { return <<'EOF'; !if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">dx9flags.mk] +!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else -!if [echo DX9_FLAGS =>dx9flags.mk] +!if [echo DX9_FLAGS =>d3d9flags.mk] !endif !endif -!if exist("dx9flags.mk") -!include "dx9flags.mk" +!if exist("d3d9flags.mk") +!include "d3d9flags.mk" !else DX9_FLAGS = !endif @@ -82,8 +82,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; - my $dx9_flags = ""; - my $dx9_block = ""; + my $d3d9_flags = ""; + my $d3d9_block = ""; if ($type eq "Borland") { $cc = "bcc32 -c"; @@ -108,8 +108,8 @@ sub generate { $inc = "/I"; $dll = "/DLL"; - $dx9_flags = "\$(DX9_FLAGS)"; - $dx9_block = dx9_detect_block(); + $d3d9_flags = "\$(DX9_FLAGS)"; + $d3d9_block = d3d9_detect_block(); } elsif ($type eq "Watcom") { $cc = "wcc386 -bt=nt -q"; @@ -132,20 +132,20 @@ sub generate { $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - $dx9_flags = "\$(DX9_FLAGS)"; - $dx9_block = dx9_detect_block(); + $d3d9_flags = "\$(DX9_FLAGS)"; + $d3d9_block = d3d9_detect_block(); } open(OUT, ">", $output); print(OUT "CC = $cc\n"); print(OUT "LD = $link\n"); print(OUT "\n"); - if ($dx9_block ne "") { - print(OUT $dx9_block); + if ($d3d9_block ne "") { + print(OUT $d3d9_block); print(OUT "\n"); } print(OUT -"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${dx9_flags}\n" +"MW_CFLAGS = ${cdll} ${inc}include ${inc}external${dir}libz${dir}include ${def}_MILSKO ${def}_MILSKO_BUILD ${def}USE_GDI ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD ${def}USE_GDI_TEXT ${def}MW_OPENGL ${d3d9_flags}\n" ); print(OUT "MW_LDFLAGS = $dll\n"); print(OUT "EXE_CFLAGS = ${inc}include\n"); @@ -181,8 +181,8 @@ sub generate { } print(OUT " $del src${dir}Mw.dll\n"); print(OUT " $del src${dir}Mw.lib\n"); - if ($dx9_block ne "") { - print(OUT " $del dx9flags.mk\n"); + if ($d3d9_block ne "") { + print(OUT " $del d3d9flags.mk\n"); } foreach my $f (@examples) { my $b = $f; From e7dc38175f2243848906b418ed42eea95d488f14 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 19 Sep 2026 01:58:40 +0900 Subject: [PATCH 157/168] experiment with cmake not trying to find directx --- CMakeLists.txt | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15cbb11..82d8a0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,15 +98,8 @@ if(MW_TRY_VULKAN) endif() if(MW_TRY_DIRECT3D9) - include(${CMAKE_CURRENT_SOURCE_DIR}/resource/FindDirectX.cmake) - if(DIRECTX_FOUND) - if(MW_TRY_DIRECT3D9) - set(MW_BUILD_DIRECT3D9 ON) - message(STATUS "Direct3D9 widget has been enabled") - endif() - else() - message(STATUS "DirectX widgets have been disabled (DirectX not found)") - endif() + set(MW_BUILD_DIRECT3D9 ON) + message(STATUS "Direct3D9 widget has been enabled") endif() if(MW_BUILD_STATIC) From 21911dd899e5450b71475b8dde64125ceccbb361 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 19 Sep 2026 02:00:27 +0900 Subject: [PATCH 158/168] Update examples/dxdemos/CMakeLists.txt --- examples/dxdemos/CMakeLists.txt | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/examples/dxdemos/CMakeLists.txt b/examples/dxdemos/CMakeLists.txt index aa09d63..1531651 100644 --- a/examples/dxdemos/CMakeLists.txt +++ b/examples/dxdemos/CMakeLists.txt @@ -3,21 +3,13 @@ file( EXAMPLES_DIRECTX_SOURCES *.c ) -include(${CMAKE_CURRENT_SOURCE_DIR}/../../resource/FindDirectX.cmake) -if(${DIRECTX_FOUND}) - foreach(PATH IN LISTS EXAMPLES_DIRECTX_SOURCES) - get_filename_component(TARGET ${PATH} NAME_WE) - add_executable(${TARGET} ${PATH}) - target_include_directories( - ${TARGET} - PRIVATE - ${DIRECTX_INCLUDE_DIRS} - ) - target_link_libraries( -${TARGET} -PRIVATE -Mw -) - endforeach() -endif() +foreach(PATH IN LISTS EXAMPLES_DIRECTX_SOURCES) + get_filename_component(TARGET ${PATH} NAME_WE) + add_executable(${TARGET} ${PATH}) + target_link_libraries( + ${TARGET} + PRIVATE + Mw + ) +endforeach() From dfa8c22f1a4453e76e9ff966a49fcf0c10a16f65 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 10:27:37 +0900 Subject: [PATCH 159/168] fix --- NTMakefile | 4 ++-- WatMakefile | 16 +--------------- tools/genmk.pl | 7 ++----- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/NTMakefile b/NTMakefile index 0383974..6712a8b 100644 --- a/NTMakefile +++ b/NTMakefile @@ -1,8 +1,8 @@ CC = cl /TC /c /nologo LD = link /nologo -!if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] +!if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where /R "%DXSDK_DIR%\\Include" d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else !if [echo DX9_FLAGS =>d3d9flags.mk] diff --git a/WatMakefile b/WatMakefile index 0702947..04a48b8 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,20 +1,7 @@ CC = wcc386 -bt=nt -q LD = wlink option quiet -!if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] -!endif -!else -!if [echo DX9_FLAGS =>d3d9flags.mk] -!endif -!endif -!if exist("d3d9flags.mk") -!include "d3d9flags.mk" -!else -DX9_FLAGS = -!endif - -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL $(DX9_FLAGS) +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt @@ -121,7 +108,6 @@ clean: .SYMBOLIC %erase src/widget/window.obj %erase src/Mw.dll %erase src/Mw.lib - %erase d3d9flags.mk %erase examples/basic/box.obj %erase examples/basic/calculator.obj %erase examples/basic/checkbox.obj diff --git a/tools/genmk.pl b/tools/genmk.pl index e8c7695..ee4822a 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -44,8 +44,8 @@ sub cobjs { sub d3d9_detect_block { return <<'EOF'; -!if [where d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] +!if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] +!if [for /f "delims=" %P in ('where /R "%DXSDK_DIR%\\Include" d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] !endif !else !if [echo DX9_FLAGS =>d3d9flags.mk] @@ -131,9 +131,6 @@ sub generate { $prefobj = "file "; $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; - - $d3d9_flags = "\$(DX9_FLAGS)"; - $d3d9_block = d3d9_detect_block(); } open(OUT, ">", $output); From 9bdd80b42188ab22017ee077f50142a39329f082 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 10:57:31 +0900 Subject: [PATCH 160/168] fix watcom --- WatMakefile | 16 +++++++++++---- include/Mw/Widget/Direct3D9.h | 3 +++ src/widget/direct3d9.c | 6 +++++- tools/genmk.pl | 38 ++++++++++++++++++++++++++++++++--- 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/WatMakefile b/WatMakefile index 04a48b8..8873675 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,13 +1,13 @@ -CC = wcc386 -bt=nt -q +CC = wcc386 -bt=nt -q -fr LD = wlink option quiet -MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL +MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT -dMW_OPENGL -dMW_DIRECT3D9 MW_LDFLAGS = system nt_dll EXE_CFLAGS = -i=include EXE_LDFLAGS = system nt -all: src/Mw.dll examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe +all: src/Mw.dll examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/dxdemos/direct3d9.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe lib: src/Mw.dll -examples: examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe +examples: examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/dnd.exe examples/basic/document.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/dxdemos/direct3d9.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe clean: .SYMBOLIC %erase external/libz/src/adler32.obj %erase external/libz/src/compress.obj @@ -131,6 +131,7 @@ clean: .SYMBOLIC %erase examples/basic/tab.obj %erase examples/basic/treeview.obj %erase examples/basic/viewport.obj + %erase examples/dxdemos/direct3d9.obj %erase examples/gldemos/boing.obj %erase examples/gldemos/clock.obj %erase examples/gldemos/cube.obj @@ -160,6 +161,7 @@ clean: .SYMBOLIC %erase examples/basic/tab.exe %erase examples/basic/treeview.exe %erase examples/basic/viewport.exe + %erase examples/dxdemos/direct3d9.exe %erase examples/gldemos/boing.exe %erase examples/gldemos/clock.exe %erase examples/gldemos/cube.exe @@ -305,6 +307,12 @@ examples/basic/viewport.exe: examples/basic/viewport.obj src/Mw.dll examples/basic/viewport.obj: examples/basic/viewport.c $(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/viewport.c +examples/dxdemos/direct3d9.exe: examples/dxdemos/direct3d9.obj src/Mw.dll + $(LD) $(EXE_LDFLAGS) name $@ file examples/dxdemos/direct3d9.obj library clib3r.lib library src/Mw.lib + +examples/dxdemos/direct3d9.obj: examples/dxdemos/direct3d9.c + $(CC) $(EXE_CFLAGS) -fo=$@ examples/dxdemos/direct3d9.c + examples/gldemos/boing.exe: examples/gldemos/boing.obj src/Mw.dll $(LD) $(EXE_LDFLAGS) name $@ file examples/gldemos/boing.obj library clib3r.lib library src/Mw.lib library opengl32.lib library glu32.lib diff --git a/include/Mw/Widget/Direct3D9.h b/include/Mw/Widget/Direct3D9.h index b6904d4..5715c1b 100644 --- a/include/Mw/Widget/Direct3D9.h +++ b/include/Mw/Widget/Direct3D9.h @@ -25,6 +25,9 @@ #error D3D9 widget only avaliable for Win32 backends #undef MW_DIRECT3D9 #else +#ifdef __WATCOMC__ +#include +#endif #include #endif #endif diff --git a/src/widget/direct3d9.c b/src/widget/direct3d9.c index 4134786..9c151e7 100644 --- a/src/widget/direct3d9.c +++ b/src/widget/direct3d9.c @@ -4,13 +4,17 @@ #include typedef struct gdid3d9 { void* d3d9dll; - IDirect3D9* (*Direct3DCreate9)(UINT sdk_version); + IDirect3D9*(D3DAPI* Direct3DCreate9)(UINT sdk_version); LPDIRECT3D9 d3d; // the pointer to our Direct3D interface LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class } gdid3d9_t; +#ifndef D3D_SDK_VERSION +#define D3D_SDK_VERSION 32 +#endif + static int wcreate_d3d9(MwWidget handle) { gdid3d9_t* o = malloc(sizeof(gdid3d9_t)); HRESULT hr; diff --git a/tools/genmk.pl b/tools/genmk.pl index ee4822a..ba5d40d 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -59,6 +59,17 @@ DX9_FLAGS = EOF } +sub skip_d3d9 { + my $f = $_[0]; + my $type = $_[1]; + + if (($f =~ /\/dxdemos\//) and not($type eq "Watcom")) { + return 1; + } + + return 0; +} + sub generate { my ($output, $type) = @_; @@ -82,8 +93,8 @@ sub generate { my $lib = ""; my $c_dllout = ""; my $c_dllafter = ""; - my $d3d9_flags = ""; - my $d3d9_block = ""; + my $d3d9_flags = ""; + my $d3d9_block = ""; if ($type eq "Borland") { $cc = "bcc32 -c"; @@ -112,7 +123,7 @@ sub generate { $d3d9_block = d3d9_detect_block(); } elsif ($type eq "Watcom") { - $cc = "wcc386 -bt=nt -q"; + $cc = "wcc386 -bt=nt -q -fr"; $link = "wlink option quiet"; $out = "-fo="; $dllout = "name "; @@ -131,6 +142,8 @@ sub generate { $prefobj = "file "; $needlibs = "${lib}clib3r.lib"; $c_dllout = "option implib=src${dir}Mw.lib"; + + $d3d9_flags = "${def}MW_DIRECT3D9"; } open(OUT, ">", $output); @@ -154,6 +167,9 @@ sub generate { } print(OUT "all: src${dir}Mw.dll"); foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } $b = $f; $b =~ s/\.c$/.exe/; $b =~ s/\//$dir/g; @@ -163,6 +179,9 @@ sub generate { print(OUT "lib: src${dir}Mw.dll\n"); print(OUT "examples:"); foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } $b = $f; $b =~ s/\.c$/.exe/; $b =~ s/\//$dir/g; @@ -171,6 +190,9 @@ sub generate { print(OUT "\n"); print(OUT "clean: $symbolic\n"); foreach my $f (@cfiles) { + if (skip_d3d9($f, $type)) { + next; + } my $b = $f; $b =~ s/\.c$/.obj/; $b =~ s/\//$dir/g; @@ -182,12 +204,18 @@ sub generate { print(OUT " $del d3d9flags.mk\n"); } foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } my $b = $f; $b =~ s/\.c$/.obj/; $b =~ s/\//$dir/g; print(OUT " $del $b\n"); } foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } $b = $f; $b =~ s/\.c$/.exe/; $b =~ s/\//$dir/g; @@ -195,6 +223,9 @@ sub generate { } print(OUT "\n"); foreach my $f (@examples) { + if (skip_d3d9($f, $type)) { + next; + } my $b = $f; $b =~ s/\.c$/.exe/; $b =~ s/\//$dir/g; @@ -256,6 +287,7 @@ push(@cfiles, "src/backend/gdi.c"); scan_examples("examples/basic"); scan_examples("examples/gldemos"); +scan_examples("examples/dxdemos"); @examples = sort(@examples); From 7d2b5a17a4e608f41fc05a6bc93f4ed95785ec3e Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:00:33 +0900 Subject: [PATCH 161/168] o --- Jenkinsfile | 4 ++-- src/widget/direct3d9.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index c506028..593d08f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -42,7 +42,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --cross --target=Windows --host=i686-w64-mingw32") + sh("./configure --enable-opengl --cross --target=Windows --host=i686-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw32.dll") sh("mv src/libMw.dll.a libMw32.dll.a") @@ -55,7 +55,7 @@ pipeline { } steps { sh("git clean -dfx") - sh("./configure --enable-opengl --enable-d3d9 --enable-d3d8 --cross --target=Windows --host=x86_64-w64-mingw32") + sh("./configure --enable-opengl --cross --target=Windows --host=x86_64-w64-mingw32") sh("make -j4") sh("mv src/Mw.dll Mw64.dll") sh("mv src/libMw.dll.a libMw64.dll.a") diff --git a/src/widget/direct3d9.c b/src/widget/direct3d9.c index 9c151e7..5d8a934 100644 --- a/src/widget/direct3d9.c +++ b/src/widget/direct3d9.c @@ -4,7 +4,7 @@ #include typedef struct gdid3d9 { void* d3d9dll; - IDirect3D9*(D3DAPI* Direct3DCreate9)(UINT sdk_version); + IDirect3D9*(WINAPI* Direct3DCreate9)(UINT sdk_version); LPDIRECT3D9 d3d; // the pointer to our Direct3D interface LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class From cdf7657b197f445e02e29c0c345f770585280b4b Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:06:13 +0900 Subject: [PATCH 162/168] ok --- NTMakefile | 2 +- configure | 2 +- tools/genmk.pl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NTMakefile b/NTMakefile index 6712a8b..a0bc3d7 100644 --- a/NTMakefile +++ b/NTMakefile @@ -2,7 +2,7 @@ CC = cl /TC /c /nologo LD = link /nologo !if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where /R "%DXSDK_DIR%\\Include" d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] +!if [echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%DXSDK_DIR%\\Include">d3d9flags.mk] !endif !else !if [echo DX9_FLAGS =>d3d9flags.mk] diff --git a/configure b/configure index 025b265..f84b1ea 100755 --- a/configure +++ b/configure @@ -246,7 +246,7 @@ print(OUT " clang-format --verbose -i `find tools src include examples \"(\" -name \"*.c\" -or -name \"*.cc\" -or -name \"*.h\" -or -name \"*.m\" \")\" -and -not -name \"*ttf.c\"`\n" ); print(OUT -" perltidy -b -bext=\"/\" --paren-tightness=2 `find tools pl configure -name \"*.pl\"`\n" +" perltidy -b -bext=\"/\" --paren-tightness=2 `find tools pl -name \"*.pl\"` configure\n" ); print(OUT "\n"); print(OUT "lib:"); diff --git a/tools/genmk.pl b/tools/genmk.pl index ba5d40d..b7993e3 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -45,7 +45,7 @@ sub cobjs { sub d3d9_detect_block { return <<'EOF'; !if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] -!if [for /f "delims=" %P in ('where /R "%DXSDK_DIR%\\Include" d3d9.h 2^>nul') do @echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%~dpP">d3d9flags.mk] +!if [echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%DXSDK_DIR%\\Include">d3d9flags.mk] !endif !else !if [echo DX9_FLAGS =>d3d9flags.mk] From 4e2c2709082a7f3791dbcd313d65f0c3f2f9eb3d Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:09:11 +0900 Subject: [PATCH 163/168] ok --- NTMakefile | 2 +- tools/genmk.pl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NTMakefile b/NTMakefile index a0bc3d7..18fbbda 100644 --- a/NTMakefile +++ b/NTMakefile @@ -1,7 +1,7 @@ CC = cl /TC /c /nologo LD = link /nologo -!if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] +!if [where /R "%DXSDK_DIR%\\Include" /Q d3d9.h] == 0 !if [echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%DXSDK_DIR%\\Include">d3d9flags.mk] !endif !else diff --git a/tools/genmk.pl b/tools/genmk.pl index b7993e3..bc97e84 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -44,7 +44,7 @@ sub cobjs { sub d3d9_detect_block { return <<'EOF'; -!if [where /R "%DXSDK_DIR%\\Include" d3d9.h >nul 2>nul] +!if [where /R "%DXSDK_DIR%\\Include" /Q d3d9.h] == 0 !if [echo DX9_FLAGS = /DMW_DIRECT3D9 /I"%DXSDK_DIR%\\Include">d3d9flags.mk] !endif !else From 75b42a2467f7e7d11b1d9c53c4943bff3208d5b9 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:18:15 +0900 Subject: [PATCH 164/168] add header --- doc/BINDINGS.md | 2 ++ doc/ENV.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/doc/BINDINGS.md b/doc/BINDINGS.md index 44014ac..ef327be 100644 --- a/doc/BINDINGS.md +++ b/doc/BINDINGS.md @@ -1,3 +1,5 @@ +# Bindings + \* = in-dev version # Active Bindings diff --git a/doc/ENV.md b/doc/ENV.md index 001c301..b6f5729 100644 --- a/doc/ENV.md +++ b/doc/ENV.md @@ -1,3 +1,5 @@ +# Environment vaiables + Platforms that support both X11 and Wayland (Linux, namely) support launching Milsko programs with following environment variables: - `MW_BACKEND`: set to either `wayland` or `x11` to force which display protocol Wayland uses From 61529b752052be33e3454fd6bc4c42373d7023d1 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:20:06 +0900 Subject: [PATCH 165/168] update header --- include/Mw/Widget/Direct3D9.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/Mw/Widget/Direct3D9.h b/include/Mw/Widget/Direct3D9.h index 5715c1b..8e7cb5b 100644 --- a/include/Mw/Widget/Direct3D9.h +++ b/include/Mw/Widget/Direct3D9.h @@ -1,6 +1,6 @@ /*! - * @file Mw/Widget/DirectX.h - * @brief DirectX widget. + * @file Mw/Widget/Direct3D9.h + * @brief Direct3D9 widget. * @warning Only avaliable on Windows. */ #ifndef __MW_WIDGET_DIRECT3D9_H__ From 941f7f0075b93cad68c081cfc3a7e51c1d93248e Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:41:23 +0900 Subject: [PATCH 166/168] fix line --- src/backend/cairo.c | 4 ++-- src/backend/wayland/wayland.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 3f1e18c..49f315c 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -31,9 +31,9 @@ void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); for(i = 0; i < 2; i++) { if(i == 0) { - cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); + cairo_move_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); } else { - cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); + cairo_line_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); } } cairo_stroke(handle.front_cairo_back); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 67429f2..c944587 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1986,7 +1986,7 @@ static int MwLLWaylandCallInitImpl(void) { #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { - loadWayland = 0; + //loadWayland = 0; } #endif From 179853c6c874aa6a5bbe32f056a400fe06a2d9e5 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 21 Sep 2026 19:45:06 -0700 Subject: [PATCH 167/168] hte w --- src/backend/cairo.c | 16 ++++++++-------- src/backend/wayland/interfaces.c | 10 +++++++++- src/backend/wayland/wayland.c | 3 +-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 49f315c..9dab1c1 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -31,9 +31,9 @@ void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); for(i = 0; i < 2; i++) { if(i == 0) { - cairo_move_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); + cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); } else { - cairo_line_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); + cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); } } cairo_stroke(handle.front_cairo_back); @@ -219,8 +219,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -264,10 +264,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 4aebb61..1b9fe1a 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -1505,11 +1505,19 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zwp_relative_pointer_manager_v1); WL_INTERFACE(xdg_wm_base); WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ - WL_INTERFACE(wl_subcompositor); if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); + WL_INTERFACE(wl_subcompositor); + WL_INTERFACE(wl_seat); WL_INTERFACE(wp_fifo_manager_v1); + } else if(wayland->type == MwLL_WAYLAND_POPUP) { + WL_INTERFACE(wl_seat); + } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { + WL_INTERFACE(wl_subcompositor); + WL_INTERFACE(wl_seat); + } else { + WL_INTERFACE(wl_subcompositor); } #undef WL_INTERFACE } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index c944587..227ced4 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -892,7 +892,6 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.parent = parent; r->wayland.valid = MwTRUE; - printf("type %d\n", ty); if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { setup_toplevel(r, x, y); @@ -1986,7 +1985,7 @@ static int MwLLWaylandCallInitImpl(void) { #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { - //loadWayland = 0; + // loadWayland = 0; } #endif From 46bc51076cc0a106bdf7e536418adf02e7fad618 Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 22 Sep 2026 11:47:44 +0900 Subject: [PATCH 168/168] fix line --- src/backend/cairo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 9dab1c1..237f6b5 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -31,9 +31,9 @@ void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) { cairo_set_source_rgba(handle.front_cairo_back, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); for(i = 0; i < 2; i++) { if(i == 0) { - cairo_move_to(handle.front_cairo_back, points[i].x, points[i].y); + cairo_move_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); } else { - cairo_line_to(handle.front_cairo_back, points[i].x, points[i].y); + cairo_line_to(handle.front_cairo_back, points[i].x + 0.5, points[i].y + 0.5); } } cairo_stroke(handle.front_cairo_back);