diff --git a/.gitignore b/.gitignore index 4e56495..58b172a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ compile_flags.txt .DS_Store /vms /BorMakefile +*.err +*.zip *.pef *.dsk diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..83daed8 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,17 @@ +========================= 1.4 ========================= +- CMakeLists.txt downgraded to version 3.13 to allow compiling on Windows XP +- CMake build now generates a pkgconfig file. +- GDI backend now natively uses GDI for text rendering +- Widgets can now be disabled with MwNdisabled +- Added `MwTabFocus` for letting a tab widget steal focus. +- New table widget (`MwTableClass`). +- Added `MwWindowShouldClose` for letting custom loops know when a window should close. +- Remove VMS build files +- Entry widgets now have blinking cursor that appears only when you hover over the widget. +- Wayland backend: + - Can now create layer surfaces (Use `MwLLMakeToolWindow` on a parentless window) + - Now properly handles keys being held down + - has drastically improved CSD (functionality wise) + - Uses KMSDRM directly for the OpenGL widget instead of wl_egl for a smoother experience + - Various overall performance improvements putting it on the same level as the X11 backend finally + - Menu widget works better under compositors that use CSD. diff --git a/CMakeLists.txt b/CMakeLists.txt index ac7f7a7..5441692 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.25) +cmake_minimum_required(VERSION 3.13) project( milsko ) @@ -9,6 +9,12 @@ include(GNUInstallDirs) set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +if(WIN32) + set(CMAKE_STATIC_LIBRARY_PREFIX "") + set(CMAKE_SHARED_LIBRARY_PREFIX "") +endif() option(MW_CLASSIC_THEME "Use classic theme" OFF) option(MW_BUILD_EXAMPLES "Build examples" OFF) @@ -29,12 +35,18 @@ endif() option(MW_INSTALL_HEADERS "Install headers" ON) -if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin OR ${CMAKE_SYSTEM_NAME} MATCHES Retro) +if( ${CMAKE_SYSTEM_NAME} STREQUAL Darwin + OR ${CMAKE_SYSTEM_NAME} MATCHES Retro + OR ${CMAKE_SYSTEM_NAME} MATCHES Windows) option(MW_USE_FREETYPE2 "Use FreeType 2" OFF) else() option(MW_USE_FREETYPE2 "Use FreeType 2" ON) endif() +if(${CMAKE_SYSTEM_NAME} STREQUAL Windows) + option(MW_USE_GDI_TEXT "Use GDI for text rendering" ON) +endif() + if(${CMAKE_SYSTEM_NAME} STREQUAL Linux OR ${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD) option(MW_USE_WAYLAND "Enable Wayland backend" ON) endif() @@ -69,8 +81,8 @@ if(MW_TRY_OPENGL) endif() if(MW_TRY_VULKAN) - check_include_files(vulkan/vulkan.h HAVE_VULKAN_VULKAN_H) - if(HAVE_VULKAN_VULKAN_H) + find_package(Vulkan) + if(${Vulkan_FOUND}) set(MW_BUILD_VULKAN ON) message(STATUS "Vulkan widget has been enabled") else() @@ -130,21 +142,29 @@ endif() if(MW_USE_FREETYPE2) find_package(Freetype) if(Freetype_FOUND) - message(STATUS "FreeType2 found") + message(STATUS "FreeType2 found") target_compile_definitions( - Mw - PRIVATE - USE_FREETYPE2 - ) + Mw + PRIVATE + USE_FREETYPE2 + ) list(APPEND INCLUDE_DIRS ${FREETYPE_INCLUDE_DIRS}) list(APPEND LIBRARY_DIRS ${FREETYPE_LIBRARY_DIRS}) - list(APPEND LIBRARIES ${FREETYPE_LIBRARIES}) else() - message(WARNING "FreeType2 not found") + message(WARNING "FreeType2 not found") endif() endif() + +if(MW_USE_GDI_TEXT) + target_compile_definitions( + Mw + PRIVATE + USE_GDI_TEXT + ) +endif() + if(MW_USE_WAYLAND) function(scan_wayland_protocol_core) execute_process( @@ -198,7 +218,32 @@ if(MW_USE_WAYLAND) ) endfunction() - + function(scan_wayland_protocol_from_file proto file) + SET(proto_c ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland/wayland-${proto}-protocol.c) + execute_process( + COMMAND wayland-scanner private-code ${CMAKE_CURRENT_SOURCE_DIR}/resource/wayland/${file} ${proto_c} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT + ERROR_VARIABLE WAYLAND_SCANNER_ERROR + ECHO_OUTPUT_VARIABLE + ECHO_ERROR_VARIABLE + COMMAND_ECHO STDOUT + ) + target_sources( + Mw + PRIVATE + ${proto_c} + ) + execute_process( + COMMAND wayland-scanner client-header ${CMAKE_CURRENT_SOURCE_DIR}/resource/wayland/${file} ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/${proto}-client-protocol.h + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT + ERROR_VARIABLE WAYLAND_SCANNER_ERROR + ECHO_OUTPUT_VARIABLE + ECHO_ERROR_VARIABLE + COMMAND_ECHO STDOUT + ) + endfunction() check_include_files(wayland-client.h HAVE_WL_H) check_include_files(xkbcommon/xkbcommon.h HAVE_XKBCOMMON_H) @@ -216,10 +261,12 @@ 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_from_file("wlr-layer-shell" "wlr-layer-shell-unstable-v1.xml") target_sources( Mw PRIVATE + src/backend/cairo.c src/backend/wayland/wayland.c src/backend/wayland/buffer.c src/backend/wayland/interfaces.c @@ -270,7 +317,8 @@ if(MW_CLASSIC_THEME) ) endif() -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") +message("Building Milsko for ${CMAKE_SYSTEM_NAME}") +if(CMAKE_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_SYSTEM_NAME STREQUAL "MSYS") target_sources( Mw PRIVATE @@ -281,12 +329,14 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") PRIVATE USE_GDI ) - list(APPEND LIBRARIES gdi32) + list(APPEND LIBRARIES gdi32 ole32 uuid) + if(NOT MSVC) target_link_options( Mw PRIVATE -static-libgcc ) + endif() elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") # target_sources( # Mw @@ -310,6 +360,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") -framework Cocoa ) elseif(CMAKE_SYSTEM_NAME MATCHES "Retro") + target_sources( Mw PRIVATE @@ -328,6 +379,7 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Retro") CLASSIC_MAC_OS ) else() + find_package(PkgConfig) find_package(X11) pkg_check_modules(DBUS dbus-1) @@ -341,7 +393,6 @@ else() if(${X11_FOUND}) list(APPEND INCLUDE_DIRS ${X11_INCLUDE_DIRS}) list(APPEND LIBRARY_DIRS ${X11_LIBRARY_DIRS}) - list(APPEND LIBRARIES ${X11_LIBRARIES} m) target_compile_definitions( Mw PRIVATE @@ -351,7 +402,6 @@ else() if(${X11_Xrender_FOUND}) list(APPEND INCLUDE_DIRS ${XRENDER_INCLUDE_DIRS}) list(APPEND LIBRARY_DIRS ${XRENDER_LIBRARY_DIRS}) - list(APPEND LIBRARIES ${XRENDER_LIBRARIES} m) target_compile_definitions( Mw PRIVATE @@ -362,19 +412,24 @@ else() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") list(APPEND LIBRARIES dl) endif() + + find_package(DBus1) + + if(${DBus1_FOUND}) + list(APPEND INCLUDE_DIRS ${DBUS_INCLUDE_DIRS}) + list(APPEND LIBRARY_DIRS ${DBUS_LIBRARY_DIRS}) + target_compile_definitions( + Mw + PRIVATE + USE_DBUS + ) + endif() endif() -find_package(DBus1) -if(${DBus1_FOUND}) - list(APPEND INCLUDE_DIRS ${DBUS_INCLUDE_DIRS}) - list(APPEND LIBRARY_DIRS ${DBUS_LIBRARY_DIRS}) - list(APPEND LIBRARIES ${DBUS_LIBRARIES}) - target_compile_definitions( - Mw - PRIVATE - USE_DBUS - ) + +if(UNIX) + list(APPEND LIBRARIES m) endif() target_include_directories( @@ -411,17 +466,20 @@ 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 ) + endif() endif() target_compile_definitions( Mw PRIVATE - _MILSKO + _MILSKO _MILSKO_BUILD ) install( @@ -431,6 +489,17 @@ install( ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/resource/${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + @ONLY + ) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + DESTINATION $ENV{MINGW_PREFIX}/${CMAKE_INSTALL_DATADIR}/pkgconfig + ) + if(MW_INSTALL_HEADERS) install( DIRECTORY include/ diff --git a/NTMakefile b/NTMakefile index b4943e7..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_TRUETYPE /DUSE_STB_IMAGE /DSTBI_NO_SIMD +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 = @@ -71,8 +71,10 @@ clean: del /f /q src\text\font\monottf.obj del /f /q src\text\font\ttf.obj del /f /q src\text\ft2.obj + del /f /q src\text\gdi.obj del /f /q src\text\stbtt.obj del /f /q src\text\text.obj + del /f /q src\truetype.obj del /f /q src\unicode.obj del /f /q src\widget\box.obj del /f /q src\widget\button.obj @@ -318,8 +320,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\stbtt.obj src\text\text.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\stbtt.obj src\text\text.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 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\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 .c.obj: diff --git a/README.txt b/README.txt index fbf3732..0f57f90 100644 --- a/README.txt +++ b/README.txt @@ -1,5 +1,5 @@ -Greetings - Welcome to the Milsko GUI Toolkit (Version 1.3) +Greetings - Welcome to the Milsko GUI Toolkit (Version 1.4) This document contains a brief summary of the contents of this source distributions and building instructions for Milsko GUI Toolkit. diff --git a/WatMakefile b/WatMakefile index bd32d9b..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_TRUETYPE -dUSE_STB_IMAGE -dSTBI_NO_SIMD +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 @@ -70,8 +70,10 @@ clean: .SYMBOLIC %erase src/text/font/monottf.obj %erase src/text/font/ttf.obj %erase src/text/ft2.obj + %erase src/text/gdi.obj %erase src/text/stbtt.obj %erase src/text/text.obj + %erase src/truetype.obj %erase src/unicode.obj %erase src/widget/box.obj %erase src/widget/button.obj @@ -317,8 +319,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/stbtt.obj src/text/text.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/stbtt.obj file src/text/text.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 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/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 @@ -444,10 +446,14 @@ src/text/font/ttf.obj: src/text/font/ttf.c $(CC) $(MW_CFLAGS) -fo=$@ src/text/font/ttf.c src/text/ft2.obj: src/text/ft2.c $(CC) $(MW_CFLAGS) -fo=$@ src/text/ft2.c +src/text/gdi.obj: src/text/gdi.c + $(CC) $(MW_CFLAGS) -fo=$@ src/text/gdi.c src/text/stbtt.obj: src/text/stbtt.c $(CC) $(MW_CFLAGS) -fo=$@ src/text/stbtt.c src/text/text.obj: src/text/text.c $(CC) $(MW_CFLAGS) -fo=$@ src/text/text.c +src/truetype.obj: src/truetype.c + $(CC) $(MW_CFLAGS) -fo=$@ src/truetype.c src/unicode.obj: src/unicode.c $(CC) $(MW_CFLAGS) -fo=$@ src/unicode.c src/widget/box.obj: src/widget/box.c diff --git a/configure b/configure index 0192a22..44db66d 100755 --- a/configure +++ b/configure @@ -2,6 +2,11 @@ our $target = `uname -s`; $target =~ s/\r?\n$//; +# MSYS with MinGW gives us some other shit idk +if (index($target, "MINGW") != -1) { + $target = "Windows"; +} + foreach my $l (@ARGV) { if ($l =~ /^--.+$/) { } @@ -39,14 +44,12 @@ require("./pl/utils.pl"); param_set("classic-theme", 0); param_set("stb-image", 1); -param_set("xrender", 1); param_set("opengl", 0); param_set("vulkan", 0); param_set("vulkan-string-helper", 1); param_set("shared", 1); param_set("static", 1); param_set("examples", 1); -param_set("dbus", 1); # (option that only makes sense on x11) param_set("allow-sloppy-focus", 0); @@ -56,7 +59,8 @@ my %features = ( "stb-image" => "use stb_image, instead use libjpeg/libpng", "stb-truetype" => "use stb_truetype", "freetype2" => "use FreeType2", - "xrender" => "use XRender", + "gdi-text" => "(Windows only) use GDI Text", + "xrender" => "(X11 only) use XRender", "opengl" => "build OpenGL widget", "vulkan" => "build Vulkan widget", "vulkan-string-helper" => "use Vulkan string helper", @@ -69,7 +73,7 @@ my %features = ( ); my @features_keys = ( "1classic-theme", "1stb-image", - "1stb-truetype", "1freetype2", + "1stb-truetype", "1freetype2", "1gdi-text", "1opengl", "2xrender", "1vulkan", "2vulkan-string-helper", "1shared", "1static", @@ -78,7 +82,10 @@ my @features_keys = ( ); sub def_platform { - if($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Windows" and $target ne "Haiku") { + if($target eq "Windows") { + param_set("freetype2", 0); + param_set("stb-truetype", 0); + } elsif($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Haiku") { param_set("freetype2", 1); param_set("stb-truetype", 0); } else { @@ -87,13 +94,20 @@ sub def_platform { } if($target eq "Linux" || $target eq "FreeBSD") { param_set("x11", 1); + param_set("xrender", 1); if(!param_get("tiny")){ param_set("wayland", 1); } + param_set("dbus", 1); } if($target eq "NetBSD" || $target eq "OpenBSD") { param_set("x11", 1); } + if($target eq "Windows") { + param_set("gdi-text", 1); + } else { + param_set("gdi-text", 0); + } } foreach my $l (@ARGV) { diff --git a/examples/basic/example.c b/examples/basic/example.c index 9facecb..8fe38da 100644 --- a/examples/basic/example.c +++ b/examples/basic/example.c @@ -1,6 +1,6 @@ #include -MwWidget window, menu, button, button2, button3, button4, button5, button6; +MwWidget window, menu, button, button2, button3, button4, button5, button6, button7; void MWAPI handler(MwWidget handle, void* user_data, void* call_data) { (void)handle; @@ -51,24 +51,29 @@ void MWAPI resize(MwWidget handle, void* user_data, void* call_data) { MwVaApply(button, MwNy, 50 + mh, - MwNwidth, (w - 50 * 2) / 3, + MwNwidth, (w - 50 * 2) / 4, MwNheight, h - 125 - 50 * 3, NULL); MwVaApply(button2, - MwNx, 50 + (w - 50 * 2) / 3, + MwNx, 50 + (w - 50 * 2) / 4, MwNy, 50 + mh, - MwNwidth, (w - 50 * 2) / 3, + MwNwidth, (w - 50 * 2) / 4, MwNheight, h - 125 - 50 * 3, NULL); MwVaApply(button3, - MwNx, 50 + (w - 50 * 2) / 3 * 2, + MwNx, 50 + (w - 50 * 2) / 4 * 2, MwNy, 50 + mh, - MwNwidth, (w - 50 * 2) / 3, + MwNwidth, (w - 50 * 2) / 4, + MwNheight, h - 125 - 50 * 3, + NULL); + MwVaApply(button7, + MwNx, 50 + (w - 50 * 2) / 4 * 3, + MwNy, 50 + mh, + MwNwidth, (w - 50 * 2) / 4, MwNheight, h - 125 - 50 * 3, NULL); - MwVaApply(button4, MwNx, 50 + (w - 50 * 2) / 3 * 0, MwNy, h - 50 - 125 + mh, @@ -121,6 +126,10 @@ int main() { MwNbackground, "#66f", MwNforeground, "#000", NULL); + button7 = MwVaCreateWidget(MwButtonClass, "button", window, 250, 50, 100, 125, + MwNtext, "disabled", + MwNdisabled, 1, + NULL); MwAddUserHandler(window, MwNresizeHandler, resize, NULL); MwAddUserHandler(button, MwNactivateHandler, handler_theme, NULL); diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c index 069395f..92dab70 100644 --- a/examples/basic/periodic.c +++ b/examples/basic/periodic.c @@ -202,9 +202,16 @@ int main() { MwNcolumns, 5, NULL); - f = frame("Button", -PaddingContent, -PaddingContent, MwButtonClass, - MwNtext, "Press me", + f = frame("Button", -PaddingContent, -PaddingContent, MwBoxClass, + MwNorientation, MwVERTICAL, NULL); + b = MwVaCreateWidget(MwButtonClass, "btn", child(f), 0, 0, 0, 0, + MwNtext, "Press me", + NULL); + b = MwVaCreateWidget(MwButtonClass, "btn_disabled", child(f), 0, 0, 0, 0, + MwNtext, "Cannot press me", + MwNdisabled, 1, + NULL); MwVaCreateWidget(MwLabelClass, "label", table, 0, 0, 0, 0, MwNbold, 1, @@ -221,11 +228,11 @@ int main() { MwNorientation, MwVERTICAL, MwNfixedSize, 16, NULL); - for(j = 0; j < 5; j++) MwCreateWidget(i == 0 ? MwCheckBoxClass : MwRadioBoxClass, i == 0 ? "cb" : "rb", b, 0, 0, 0, 0); + for(j = 0; j < 6; j++) MwVaCreateWidget(i == 0 ? MwCheckBoxClass : MwRadioBoxClass, i == 0 ? "cb" : "rb", b, 0, 0, 0, 0, MwNdisabled, (j == 5) ? 1 : 0, NULL); b = MwVaCreateWidget(MwBoxClass, "table1", w, 0, 0, 0, 0, MwNorientation, MwVERTICAL, NULL); - for(j = 0; j < 5; j++) { + for(j = 0; j < 6; j++) { char buf[32]; sprintf(buf, "%sBox %d", i == 0 ? "Check" : "Radio", j + 1); MwVaCreateWidget(MwLabelClass, "label", b, 0, 0, 0, 0, diff --git a/examples/basic/tab.c b/examples/basic/tab.c index 8b0ad4a..8ae16c0 100644 --- a/examples/basic/tab.c +++ b/examples/basic/tab.c @@ -31,6 +31,10 @@ int main() { MwTabAdd(tab, buf); } + MwVaApply(MwTabGetFrame(tab, "Tab 1"), + MwNiconPixmap, MwLoadIcon(tab, MwIconWarning), + NULL); + MwAddUserHandler(w, MwNresizeHandler, resize, NULL); resize(w, NULL, NULL); diff --git a/examples/vkdemos/CMakeLists.txt b/examples/vkdemos/CMakeLists.txt index 41f832c..9f37e0f 100644 --- a/examples/vkdemos/CMakeLists.txt +++ b/examples/vkdemos/CMakeLists.txt @@ -1,28 +1,30 @@ file( - GLOB - EXAMPLES_VULKAN_SOURCES - *.c + GLOB + EXAMPLES_VULKAN_SOURCES + *.c ) find_package(Vulkan) -foreach(PATH IN LISTS EXAMPLES_VULKAN_SOURCES) - get_filename_component(TARGET ${PATH} NAME_WE) - add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) - target_include_directories( - ${TARGET} - PRIVATE - ${Vulkan_INCLUDE_DIR} - ) - target_link_libraries( - ${TARGET} - PRIVATE - Mw - ) - if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - target_link_libraries( - ${TARGET} - PRIVATE - m - ) - endif() -endforeach() +if(${Vulkan_FOUND}) + foreach(PATH IN LISTS EXAMPLES_VULKAN_SOURCES) + get_filename_component(TARGET ${PATH} NAME_WE) + add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) + target_include_directories( + ${TARGET} + PRIVATE + ${Vulkan_INCLUDE_DIR} + ) + target_link_libraries( + ${TARGET} + PRIVATE + Mw + ) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_link_libraries( + ${TARGET} + PRIVATE + m + ) + endif() + endforeach() +endif() diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 2d03030..9060a97 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -1,10 +1,3 @@ - -/** - * this example is quite minimal, you may need to modify it if your graphics card is more esoteric - * - * ioixd maintains this file. nishi doesn't know vulkan at all - */ - #include #include diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index ae42899..deefe0f 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -28,6 +28,12 @@ MWDECL MwLLColor MWAPI MwParseColor(MwWidget handle, const char* text); */ MWDECL void MWAPI MwParseColorNoAllocate(const char* text, MwRGB* rgb); +/*! + * @brief Initialize color table + * @warning This is called in MwLibraryInit - you do not have to call this + */ +MWDECL void MWAPI MwColorTableInit(void); + /*! * @brief Lighten a color * @param handle Widget diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 2ba2265..6647672 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -132,6 +132,7 @@ union _MwLL { #endif #ifdef USE_WAYLAND struct _MwLLWayland wayland; + struct _MwLLCairo cairo; #endif #ifdef USE_COCOA struct _MwLLCocoa cocoa; @@ -153,7 +154,7 @@ union _MwLLColor { struct _MwLLGDIColor gdi; #endif #ifdef USE_WAYLAND - struct _MwLLWaylandColor wayland; + struct _MwLLCairoColor wayland; #endif #ifdef USE_COCOA struct _MwLLCocoaColor cocoa; @@ -173,6 +174,7 @@ union _MwLLPixmap { #endif #ifdef USE_WAYLAND struct _MwLLWaylandPixmap wayland; + struct _MwLLCairoPixmap cairo; /* same structure but we do this for code clarity */ #endif #ifdef USE_COCOA struct _MwLLCocoaPixmap cocoa; @@ -203,6 +205,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 { @@ -313,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 @@ -337,18 +346,29 @@ MWDECL void (*MwLLClip)(MwLL handle, MwRect* rect); MWDECL void MwFLSetup(void); #ifdef USE_FREETYPE2 -MWDECL int MWFL_FT2Setup(void); +MWDECL int MwFL_FT2Setup(void); #endif #ifdef USE_STB_TRUETYPE MWDECL int MwFL_STBTTSetup(void); #endif +#ifdef USE_GDI_TEXT +MWDECL int MwFL_GDISetup(void); +#endif + MWDECL int (*MwFLDrawText)(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwLLColor color); MWDECL int (*MwFLTextWidth)(MwFLFont ttf, const char* text); MWDECL int (*MwFLTextHeight)(MwFLFont ttf, int count); +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 +MWDECL void *MwLL_winmmLib; +MWDECL long (__stdcall* MwLL_PFN_timeGetTime)(void); +MWDECL unsigned int (__stdcall* MwLL_PFN_timeBeginPeriod)(unsigned int period); +#endif + #ifdef __cplusplus } #endif diff --git a/include/Mw/LowLevel/Cairo.h b/include/Mw/LowLevel/Cairo.h new file mode 100644 index 0000000..dd2cfa3 --- /dev/null +++ b/include/Mw/LowLevel/Cairo.h @@ -0,0 +1,229 @@ +/*! + * @file Mw/LowLevel/Cairo.h + * @brief Cairo Backend + * @warning This is used MEGA internally. + */ +#ifndef __MW_LOWLEVEL_CAIRO_H__ +#define __MW_LOWLEVEL_CAIRO_H__ + +#include +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +MWDECL int MwLLCairoCallInit(void); + +#ifdef __cplusplus +} +#endif + +#define CSD_BORDER_FRAME_LEFT 5 +#define CSD_BORDER_FRAME_RIGHT 5 +#define CSD_BORDER_FRAME_TOP 23 +#define CSD_BORDER_FRAME_BOTTOM 4 + +typedef struct cairo_call_table { + void* cairo_lib; + + void (*cairo_set_line_width)(cairo_t* cr, + double width); + void (*cairo_scale)(cairo_t* cr, + double sx, + double sy); + cairo_t* (*cairo_create)(cairo_surface_t* target); + void (*cairo_move_to)(cairo_t* cr, + double x, + double y); + + void (*cairo_rectangle)(cairo_t* cr, + double x, + double y, + double width, + double height); + void (*cairo_new_path)(cairo_t* cr); + void (*cairo_set_line_cap)(cairo_t* cr, + cairo_line_cap_t line_cap); + void (*cairo_set_source_rgba)(cairo_t* cr, + double red, + double green, + double blue, + double alpha); + void (*cairo_set_source_rgb)(cairo_t* cr, + double red, + double green, + double blue); + void (*cairo_reset_clip)(cairo_t* cr); + unsigned char* (*cairo_image_surface_get_data)(cairo_surface_t* surface); + void (*cairo_line_to)(cairo_t* cr, + double x, + double y); + cairo_status_t (*cairo_surface_write_to_png)(cairo_surface_t* surface, const char* filename); + void (*cairo_surface_destroy)(cairo_surface_t* surface); + cairo_surface_t* (*cairo_image_surface_create_for_data)(unsigned char* data, + cairo_format_t format, + int width, + int height, + int stride); + cairo_surface_t* (*cairo_image_surface_create)(cairo_format_t format, + int width, + int height); + void (*cairo_destroy)(cairo_t* cr); + cairo_pattern_t* (*cairo_get_source)(cairo_t* cr); + void (*cairo_close_path)(cairo_t* cr); + void (*cairo_paint)(cairo_t* cr); + void (*cairo_surface_flush)(cairo_surface_t* surface); + void (*cairo_clip)(cairo_t* cr); + void (*cairo_save)(cairo_t* cr); + void (*cairo_restore)(cairo_t* cr); + void (*cairo_surface_mark_dirty)(cairo_surface_t* surface); + void (*cairo_stroke)(cairo_t* cr); + void (*cairo_set_source_surface)(cairo_t* cr, + cairo_surface_t* surface, + double x, + double y); + void (*cairo_fill)(cairo_t* cr); + void (*cairo_pattern_set_filter)(cairo_pattern_t* pattern, + cairo_filter_t filter); + void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t); + void (*cairo_set_operator)(cairo_t* cr, cairo_operator_t op); + +} cairo_call_table_t; + +extern cairo_call_table_t cairo_call_tbl; + +/* defined inline right here so that it doesn't conflict with the other macros */ +MwInline int cairo_load_funcs() { +#ifdef __APPLE__ + cairo_call_tbl.cairo_lib = MwDynamicOpen("libcairo.dylib"); +#else + cairo_call_tbl.cairo_lib = MwDynamicOpen("libcairo.so"); +#endif + if(!cairo_call_tbl.cairo_lib) { + printf("(libcairo not found, cannot use Wayland or Cairo backend.)\n"); + return 1; + } + +#define CAIRO_FUNC(x) \ + cairo_call_tbl.x = MwDynamicSymbol(cairo_call_tbl.cairo_lib, #x); \ + if(!cairo_call_tbl.x) { \ + printf("WARNING: Could use Wayland/Cairo backend if " #x " was not found. Do you have libcairo?\n"); \ + return 1; \ + }; + + CAIRO_FUNC(cairo_set_line_width); + CAIRO_FUNC(cairo_scale); + CAIRO_FUNC(cairo_create); + CAIRO_FUNC(cairo_move_to); + CAIRO_FUNC(cairo_rectangle); + CAIRO_FUNC(cairo_new_path); + CAIRO_FUNC(cairo_set_line_cap); + CAIRO_FUNC(cairo_set_antialias); + CAIRO_FUNC(cairo_set_source_rgba); + CAIRO_FUNC(cairo_set_source_rgb); + CAIRO_FUNC(cairo_reset_clip); + CAIRO_FUNC(cairo_image_surface_get_data); + CAIRO_FUNC(cairo_line_to); + CAIRO_FUNC(cairo_surface_write_to_png); + CAIRO_FUNC(cairo_surface_destroy); + CAIRO_FUNC(cairo_image_surface_create_for_data); + CAIRO_FUNC(cairo_image_surface_create); + CAIRO_FUNC(cairo_destroy); + CAIRO_FUNC(cairo_get_source); + CAIRO_FUNC(cairo_close_path); + CAIRO_FUNC(cairo_paint); + CAIRO_FUNC(cairo_surface_flush); + CAIRO_FUNC(cairo_clip); + CAIRO_FUNC(cairo_save); + CAIRO_FUNC(cairo_restore); + CAIRO_FUNC(cairo_surface_mark_dirty); + CAIRO_FUNC(cairo_stroke); + CAIRO_FUNC(cairo_set_source_surface); + CAIRO_FUNC(cairo_fill); + CAIRO_FUNC(cairo_set_operator); + CAIRO_FUNC(cairo_pattern_set_filter); +#undef CAIRO_FUNC + + return 0; +} + +#define cairo_set_line_width cairo_call_tbl.cairo_set_line_width +#define cairo_scale cairo_call_tbl.cairo_scale +#define cairo_create cairo_call_tbl.cairo_create +#define cairo_move_to cairo_call_tbl.cairo_move_to +#define cairo_rectangle cairo_call_tbl.cairo_rectangle +#define cairo_new_path cairo_call_tbl.cairo_new_path +#define cairo_set_line_cap cairo_call_tbl.cairo_set_line_cap +#define cairo_set_antialias cairo_call_tbl.cairo_set_antialias +#define cairo_set_source_rgba cairo_call_tbl.cairo_set_source_rgba +#define cairo_set_source_rgb cairo_call_tbl.cairo_set_source_rgb +#define cairo_reset_clip cairo_call_tbl.cairo_reset_clip +#define cairo_image_surface_get_data cairo_call_tbl.cairo_image_surface_get_data +#define cairo_line_to cairo_call_tbl.cairo_line_to +#define cairo_surface_write_to_png cairo_call_tbl.cairo_surface_write_to_png +#define cairo_surface_destroy cairo_call_tbl.cairo_surface_destroy +#define cairo_image_surface_create_for_data cairo_call_tbl.cairo_image_surface_create_for_data +#define cairo_image_surface_create cairo_call_tbl.cairo_image_surface_create +#define cairo_destroy cairo_call_tbl.cairo_destroy +#define cairo_get_source cairo_call_tbl.cairo_get_source +#define cairo_close_path cairo_call_tbl.cairo_close_path +#define cairo_paint cairo_call_tbl.cairo_paint +#define cairo_surface_flush cairo_call_tbl.cairo_surface_flush +#define cairo_clip cairo_call_tbl.cairo_clip +#define cairo_save cairo_call_tbl.cairo_save +#define cairo_restore cairo_call_tbl.cairo_restore +#define cairo_surface_mark_dirty cairo_call_tbl.cairo_surface_mark_dirty +#define cairo_stroke cairo_call_tbl.cairo_stroke +#define cairo_set_source_surface cairo_call_tbl.cairo_set_source_surface +#define cairo_fill cairo_call_tbl.cairo_fill +#define cairo_set_operator cairo_call_tbl.cairo_set_operator +#define cairo_pattern_set_filter cairo_call_tbl.cairo_pattern_set_filter + +struct _MwLLCairo { + struct _MwLLCommon common; + + cairo_surface_t* front_cs; + cairo_surface_t* back_cs; + cairo_t* front_cairo; + 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; + + int x; + int y; + int width; + int height; + + MwBool toplevel; + MwLL parent; +}; + +struct _MwLLCairoColor { + struct _MwLLCommonColor common; +}; + +struct _MwLLCairoPixmap { + struct _MwLLCommonPixmap common; + + cairo_surface_t* cs; +}; + +void MwLLCairoFrontSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height); +void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height); +void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo); +void MwLLCairoBackDestroy(struct _MwLLCairo* cairo); +void MwLLCairoPolygon(struct _MwLLCairo handle, MwPoint* points, int points_count, MwLLColor color); +void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color); +MwLLPixmap MwLLCairoCreatePixmap(struct _MwLLCairo handle, unsigned char* data, int width, int height); +void MwLLCairoPixmapUpdate(MwLLPixmap handle); +void MwLLCairoDestroyPixmap(MwLLPixmap pixmap); +void MwLLCairoDrawPixmap(struct _MwLLCairo handle, MwRect* rect, MwLLPixmap pixmap); + +void MwLLCairoDestroy(struct _MwLLCairo handle); + +#endif diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c6d397b..ccd1f2f 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -11,10 +11,10 @@ #include #include +#include + #include -#include #include -#include #ifdef __cplusplus extern "C" { @@ -28,8 +28,8 @@ MWDECL int MwLLWaylandCallInit(void); #define CSD_BORDER_FRAME_LEFT 5 #define CSD_BORDER_FRAME_RIGHT 5 -#define CSD_BORDER_FRAME_TOP 24 -#define CSD_BORDER_FRAME_BOTTOM 5 +#define CSD_BORDER_FRAME_TOP 23 +#define CSD_BORDER_FRAME_BOTTOM 4 struct _MwLLWayland; @@ -43,7 +43,6 @@ struct _MwLLWayland; typedef struct wayland_call_table { void* lib; void* xkb_lib; - void* cairo_lib; #ifdef USE_DBUS MwLLDBusFuncTable dbus; MwBool has_dbus; @@ -80,67 +79,6 @@ typedef struct wayland_call_table { xkb_layout_index_t (*xkb_state_key_get_layout)(struct xkb_state* state, xkb_keycode_t key); void (*xkb_keymap_unref)(struct xkb_keymap* keymap); - void (*cairo_set_line_width)(cairo_t* cr, - double width); - void (*cairo_scale)(cairo_t* cr, - double sx, - double sy); - cairo_t* (*cairo_create)(cairo_surface_t* target); - void (*cairo_move_to)(cairo_t* cr, - double x, - double y); - - void (*cairo_rectangle)(cairo_t* cr, - double x, - double y, - double width, - double height); - void (*cairo_new_path)(cairo_t* cr); - void (*cairo_set_line_cap)(cairo_t* cr, - cairo_line_cap_t line_cap); - void (*cairo_set_source_rgba)(cairo_t* cr, - double red, - double green, - double blue, - double alpha); - void (*cairo_set_source_rgb)(cairo_t* cr, - double red, - double green, - double blue); - void (*cairo_reset_clip)(cairo_t* cr); - unsigned char* (*cairo_image_surface_get_data)(cairo_surface_t* surface); - void (*cairo_line_to)(cairo_t* cr, - double x, - double y); - void (*cairo_surface_destroy)(cairo_surface_t* surface); - cairo_surface_t* (*cairo_image_surface_create_for_data)(unsigned char* data, - cairo_format_t format, - int width, - int height, - int stride); - cairo_surface_t* (*cairo_image_surface_create)(cairo_format_t format, - int width, - int height); - void (*cairo_destroy)(cairo_t* cr); - cairo_pattern_t* (*cairo_get_source)(cairo_t* cr); - void (*cairo_close_path)(cairo_t* cr); - void (*cairo_paint)(cairo_t* cr); - void (*cairo_surface_flush)(cairo_surface_t* surface); - void (*cairo_clip)(cairo_t* cr); - void (*cairo_save)(cairo_t* cr); - void (*cairo_restore)(cairo_t* cr); - void (*cairo_surface_mark_dirty)(cairo_surface_t* surface); - void (*cairo_stroke)(cairo_t* cr); - void (*cairo_set_source_surface)(cairo_t* cr, - cairo_surface_t* surface, - double x, - double y); - void (*cairo_fill)(cairo_t* cr); - void (*cairo_pattern_set_filter)(cairo_pattern_t* pattern, - cairo_filter_t filter); - void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t); - void (*cairo_set_operator)(cairo_t* cr, cairo_operator_t op); - } wayland_call_table_t; extern wayland_call_table_t wl_call_tbl; @@ -150,6 +88,8 @@ extern MwBool MwWaylandVulkan; #define MwWaylandVulkan 0 #endif +MWDECL MwBool MwWaylandCairoOnly; + /* defined inline right here so that it doesn't conflict with the other macros */ MwInline int wayland_load_funcs() { #ifdef __APPLE__ @@ -170,15 +110,7 @@ MwInline int wayland_load_funcs() { printf("(libxkbcommon not found, cannot use Wayland backend.)\n"); return 1; } -#ifdef __APPLE__ - wl_call_tbl.cairo_lib = MwDynamicOpen("libcairo.dylib"); -#else - wl_call_tbl.cairo_lib = MwDynamicOpen("libcairo.so"); -#endif - if(!wl_call_tbl.cairo_lib) { - printf("(libcairo not found, cannot use Wayland backend.)\n"); - return 1; - } + #define WAYLAND_FUNC(x) \ wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.lib, #x); \ if(!wl_call_tbl.x) { \ @@ -224,44 +156,9 @@ MwInline int wayland_load_funcs() { XKB_FUNC(xkb_state_key_get_layout) #undef XKB_FUNC -#define CAIRO_FUNC(x) \ - wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.cairo_lib, #x); \ - if(!wl_call_tbl.x) { \ - printf("WARNING: Could use Wayland backend if " #x " was found. Do you have libcairo?\n"); \ - return 1; \ - }; - - CAIRO_FUNC(cairo_set_line_width); - CAIRO_FUNC(cairo_scale); - CAIRO_FUNC(cairo_create); - CAIRO_FUNC(cairo_move_to); - CAIRO_FUNC(cairo_rectangle); - CAIRO_FUNC(cairo_new_path); - CAIRO_FUNC(cairo_set_line_cap); - CAIRO_FUNC(cairo_set_antialias); - CAIRO_FUNC(cairo_set_source_rgba); - CAIRO_FUNC(cairo_set_source_rgb); - CAIRO_FUNC(cairo_reset_clip); - CAIRO_FUNC(cairo_image_surface_get_data); - CAIRO_FUNC(cairo_line_to); - CAIRO_FUNC(cairo_surface_destroy); - CAIRO_FUNC(cairo_image_surface_create_for_data); - CAIRO_FUNC(cairo_image_surface_create); - CAIRO_FUNC(cairo_destroy); - CAIRO_FUNC(cairo_get_source); - CAIRO_FUNC(cairo_close_path); - CAIRO_FUNC(cairo_paint); - CAIRO_FUNC(cairo_surface_flush); - CAIRO_FUNC(cairo_clip); - CAIRO_FUNC(cairo_save); - CAIRO_FUNC(cairo_restore); - CAIRO_FUNC(cairo_surface_mark_dirty); - CAIRO_FUNC(cairo_stroke); - CAIRO_FUNC(cairo_set_source_surface); - CAIRO_FUNC(cairo_fill); - CAIRO_FUNC(cairo_set_operator); - CAIRO_FUNC(cairo_pattern_set_filter); -#undef CAIRO_FUNC + if(cairo_load_funcs() != 0) { + return 1; + } #ifdef USE_DBUS wl_call_tbl.has_dbus = MwLLDBusFuncSetup(&wl_call_tbl.dbus); @@ -298,37 +195,6 @@ MwInline int wayland_load_funcs() { #define xkb_keymap_key_get_syms_by_level wl_call_tbl.xkb_keymap_key_get_syms_by_level #define xkb_state_key_get_layout wl_call_tbl.xkb_state_key_get_layout -#define cairo_set_line_width wl_call_tbl.cairo_set_line_width -#define cairo_scale wl_call_tbl.cairo_scale -#define cairo_create wl_call_tbl.cairo_create -#define cairo_move_to wl_call_tbl.cairo_move_to -#define cairo_rectangle wl_call_tbl.cairo_rectangle -#define cairo_new_path wl_call_tbl.cairo_new_path -#define cairo_set_line_cap wl_call_tbl.cairo_set_line_cap -#define cairo_set_antialias wl_call_tbl.cairo_set_antialias -#define cairo_set_source_rgba wl_call_tbl.cairo_set_source_rgba -#define cairo_set_source_rgb wl_call_tbl.cairo_set_source_rgb -#define cairo_reset_clip wl_call_tbl.cairo_reset_clip -#define cairo_image_surface_get_data wl_call_tbl.cairo_image_surface_get_data -#define cairo_line_to wl_call_tbl.cairo_line_to -#define cairo_surface_destroy wl_call_tbl.cairo_surface_destroy -#define cairo_image_surface_create_for_data wl_call_tbl.cairo_image_surface_create_for_data -#define cairo_image_surface_create wl_call_tbl.cairo_image_surface_create -#define cairo_destroy wl_call_tbl.cairo_destroy -#define cairo_get_source wl_call_tbl.cairo_get_source -#define cairo_close_path wl_call_tbl.cairo_close_path -#define cairo_paint wl_call_tbl.cairo_paint -#define cairo_surface_flush wl_call_tbl.cairo_surface_flush -#define cairo_clip wl_call_tbl.cairo_clip -#define cairo_save wl_call_tbl.cairo_save -#define cairo_restore wl_call_tbl.cairo_restore -#define cairo_surface_mark_dirty wl_call_tbl.cairo_surface_mark_dirty -#define cairo_stroke wl_call_tbl.cairo_stroke -#define cairo_set_source_surface wl_call_tbl.cairo_set_source_surface -#define cairo_fill wl_call_tbl.cairo_fill -#define cairo_set_operator wl_call_tbl.cairo_set_operator -#define cairo_pattern_set_filter wl_call_tbl.cairo_pattern_set_filter - #ifndef WL_PROTOCOLS_DEFINED #define WL_PROTOCOLS_DEFINED #include "Wayland/wayland-core-protocol.h" @@ -340,6 +206,7 @@ MwInline int wayland_load_funcs() { #include "Wayland/pointer-constraints-client-protocol.h" #include "Wayland/relative-pointer-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h" +#include "Wayland/wlr-layer-shell-client-protocol.h" #endif typedef struct wayland_protocol { @@ -347,7 +214,7 @@ typedef struct wayland_protocol { void* context; } wayland_protocol_t; -typedef wayland_protocol_t*(wl_setup_func)(MwU32, struct _MwLLWayland*); +typedef wayland_protocol_t*(wl_setup_func)(MwU32, struct _MwLLWayland*, MwU32 version); typedef void(wl_destroy_func)(struct _MwLLWayland* wayland, wayland_protocol_t* data); typedef struct wayland_protocol_callback_table { @@ -360,6 +227,7 @@ struct _MwLLWaylandTopLevel { struct xdg_toplevel* xdg_top_level; struct xdg_toplevel_listener xdg_toplevel_listener; struct xdg_surface_listener xdg_surface_listener; + MwBool maxim_state; MwBool compositor_created; MwBool xdg_wm_base_created; @@ -387,6 +255,10 @@ struct _MwLLWaylandPopup { MwLL topmost_parent; }; +struct _MwLLWaylandLayerSurface { + struct zwlr_layer_surface_v1* surface; +}; + /* Shared set of anything needed for a shm buffer. */ struct _MwLLWaylandShmBuffer { struct wl_shm* shm; @@ -410,6 +282,7 @@ enum _MwLLWaylandType { MwLL_WAYLAND_TOPLEVEL, MwLL_WAYLAND_SUBLEVEL, MwLL_WAYLAND_POPUP, + MwLL_WAYLAND_LAYER_SURFACE, }; typedef struct wl_clipboard_device_context { @@ -428,6 +301,7 @@ typedef struct wl_clipboard_device_context { struct _MwLLWayland { struct _MwLLCommon common; + struct _MwLLCairo cairo; union { /* Pointer for data that's only loaded if the widget is a toplevel */ @@ -436,6 +310,8 @@ struct _MwLLWayland { struct _MwLLWaylandSublevel* sublevel; /* Pointer for data that's only loaded if the widget is a popup */ struct _MwLLWaylandPopup* popup; + /* Pointer for data that's only loaded if the widget is a layer surface */ + struct _MwLLWaylandLayerSurface* layer_surface; }; enum _MwLLWaylandType type; @@ -444,6 +320,7 @@ struct _MwLLWayland { MwRect clipping_rect; MwBool no; + MwBool changing; MwBool detatching; MwPoint detach_point; @@ -466,6 +343,7 @@ struct _MwLLWayland { wayland_protocol_t* value; }* wl_protocol_map; + MwBool do_csd; MwBool has_decorations; char title[256]; @@ -537,6 +415,7 @@ struct _MwLLWayland { MwU32 ww, wh; /* Window position */ MwPoint cur_mouse_pos; /* Currently known mouse position */ MwLL currentlyHeldWidget; + MwLL focusedWidget; int resizing; int setting_wh; @@ -550,11 +429,15 @@ struct _MwLLWayland { MwBool dispatching_resize; + MwBool is_toplevel_menu; + struct _MwLLWaylandShmBuffer framebuffer; struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; struct _MwLLWaylandShmBuffer* icon; + MwLLPixmap icon_pixmap; + pthread_mutex_t eventsMutex; int cancelEvent; @@ -564,23 +447,20 @@ struct _MwLLWayland { MwBool moving; - cairo_surface_t* front_cs; - cairo_surface_t* back_cs; - cairo_t* front_cairo; - cairo_t* back_cairo; - /* The cairo to actually use for draw operations. Typically is front_cairo, but MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */ - cairo_t* selected_cairo; + MwI64 keyboard_rate; + MwI32 keyboard_delay; + int last_pressed_key; + MwBool holding_key; + MwU64 next_elapsed; + long start_time; + long end_time; }; struct _MwLLWaylandColor { struct _MwLLCommonColor common; }; -struct _MwLLWaylandPixmap { - struct _MwLLCommonPixmap common; - - cairo_surface_t* cs; -}; +#define _MwLLWaylandPixmap _MwLLCairoPixmap /* Setup the framebuffer with the saved width/height */ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland); diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 0415b4c..4c98b24 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -25,6 +25,7 @@ #ifdef _MILSKO #include +#include #ifndef GWLP_USERDATA #define GWLP_USERDATA GWL_USERDATA #define GWLP_WNDPROC GWL_WNDPROC diff --git a/include/Mw/Milsko.h b/include/Mw/Milsko.h index f7b4b49..9860990 100644 --- a/include/Mw/Milsko.h +++ b/include/Mw/Milsko.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 3a019e0..6ad4e46 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -52,6 +52,8 @@ #define MwNcolumns "Icolumns" #define MwNcolumnSpan "IcolumnSpan" #define MwNrowSpan "IrowSpan" +#define MwNdisabled "Idisabled" +#define MwNacceptsDnD "IacceptsDnD" #define MwNtitle "Stitle" #define MwNtext "Stext" @@ -97,5 +99,6 @@ #define MwNdrawHandler "Cdraw" #define MwNclipboardHandler "Cclipboard" #define MwNdarkThemeHandler "CdarkTheme" +#define MwNdragAndDropHandler "CdragAndDrop" #endif diff --git a/include/Mw/TrueType.h b/include/Mw/TrueType.h new file mode 100644 index 0000000..eea90c9 --- /dev/null +++ b/include/Mw/TrueType.h @@ -0,0 +1,33 @@ +/*! + * @file Mw/TrueType.h + * @brief TrueType utilities + */ +#ifndef __MW_TRUETYPE_H__ +#define __MW_TRUETYPE_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @brief Get the TrueType font information + * @param data Font data + * @param size Font size + * @return Information + */ +MWDECL MwTTFInfo MwTTFGetInfo(unsigned char* data, int size); + +/*! + * @brief Free the TrueType font information + * @param info Information + */ +MWDECL void MwTTFFreeInfo(MwTTFInfo info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 8bfa8c1..ad072a3 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -31,6 +31,7 @@ typedef struct _MwSubWindow* MwSubWindow; typedef struct _MwTab* MwTab; typedef struct _MwTable* MwTable; typedef struct _MwMouse MwMouse; +typedef struct _MwTTFInfo* MwTTFInfo; #ifdef _MILSKO typedef struct _MwWidget* MwWidget; #else @@ -40,7 +41,7 @@ typedef void (*MwHandler)(MwWidget handle); typedef int (*MwHandlerWithStatus)(MwWidget handle); typedef void (*MwHandlerProps)(MwWidget handle, char** key); typedef void (*MwHandlerProp)(MwWidget handle, const char* key); -typedef void (*MwHandlerChildrenUpdate)(MwWidget handle, MwWidget child, int new); +typedef void (*MwHandlerChildrenUpdate)(MwWidget handle, MwWidget child, int new_child); typedef void (*MwHandlerChildrenProp)(MwWidget handle, MwWidget child, const char* key); typedef void (*MwHandlerKey)(MwWidget handle, int key); typedef void (*MwHandlerMouse)(MwWidget handle, void* ptr); @@ -115,9 +116,13 @@ struct _MwWidget { int top_step; MwWidget* draw_queue; + MwWidget* resize_queue; + MwWidget* monitored_entries; int berserk; long last_tick; + + MwBool is_menu; }; #endif @@ -134,6 +139,8 @@ struct _MwEntry { int cursor; int right; int length; + int active; + int cursor_blink_timer; MwPoint mouse; }; @@ -244,6 +251,11 @@ struct _MwMouse { int button; }; +struct _MwTTFInfo { + char* family; + int weight; +}; + struct _MwClass { MwHandlerWithStatus create; MwHandler destroy; @@ -262,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/include/Mw/Version.h b/include/Mw/Version.h index 5fb57f6..9821dc6 100644 --- a/include/Mw/Version.h +++ b/include/Mw/Version.h @@ -23,7 +23,7 @@ /*! * @brief Version in string */ -#define MwVERSION "1.3" +#define MwVERSION "1.4" /*! * @brief Version in string diff --git a/include/Mw/Widget/Tab.h b/include/Mw/Widget/Tab.h index ea30023..9f80a0d 100644 --- a/include/Mw/Widget/Tab.h +++ b/include/Mw/Widget/Tab.h @@ -42,6 +42,16 @@ MwInline MwWidget MwTabGetFrame(MwWidget handle, const char* name) { return out; } +/*! + * @brief Focus on a tab frame + * @param handle Widget + * @param name Tab name + * @return Frame + */ +MwInline void MwTabFocus(MwWidget handle, const char* name) { + MwVaWidgetExecute(handle, "mwTabFocus", NULL, name); +} + #ifdef __cplusplus } #endif diff --git a/include/Mw/Widget/Window.h b/include/Mw/Widget/Window.h index 24b7153..6a98b68 100644 --- a/include/Mw/Widget/Window.h +++ b/include/Mw/Widget/Window.h @@ -27,6 +27,17 @@ MwInline void MwWindowMakeBorderless(MwWidget handle, int toggle) { MwVaWidgetExecute(handle, "mwWindowMakeBorderless", NULL, toggle); } +/*! + * @brief Whether the window should close + * @param handle Widget + * @return bool + */ +MwInline MwBool MwWindowShouldClose(MwWidget handle) { + MwBool res = MwFALSE; + MwVaWidgetExecute(handle, "mwWindowShouldClose", NULL, &res); + return res; +} + #ifdef __cplusplus } #endif diff --git a/milsko.xml b/milsko.xml index 837934e..a94c847 100644 --- a/milsko.xml +++ b/milsko.xml @@ -668,6 +668,7 @@ + @@ -961,6 +962,11 @@ + + + + + diff --git a/pl/ostype/Windows.pl b/pl/ostype/Windows.pl index 29bdc98..e2ed1ab 100644 --- a/pl/ostype/Windows.pl +++ b/pl/ostype/Windows.pl @@ -4,5 +4,7 @@ $executable_suffix = ".exe"; $math = ""; add_ldflags("-Wl,--out-implib,src/libMw.dll.a -static-libgcc"); use_backend("gdi"); +add_libs("-lole32"); +add_libs("-luuid"); 1; diff --git a/pl/rules.pl b/pl/rules.pl index 52f3c2a..89f13e9 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -46,6 +46,7 @@ if (grep(/^classicmacos$/, @backends)) { if (grep(/^wayland$/, @backends)) { add_cflags("-DUSE_WAYLAND"); + 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/interfaces.c"); @@ -65,6 +66,8 @@ 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"); $gl_libs = "-lGL -lGLU"; } @@ -132,6 +135,10 @@ if (param_get("freetype2")) { } } +if (param_get("gdi-text")) { + add_cflags("-DUSE_GDI_TEXT"); +} + if (param_get("vulkan") && param_get("vulkan-string-helper")) { add_cflags("-DHAS_VK_ENUM_STRING_HELPER"); } diff --git a/pl/utils.pl b/pl/utils.pl index a86cbbe..504e8dc 100644 --- a/pl/utils.pl +++ b/pl/utils.pl @@ -125,6 +125,35 @@ sub scan_wayland_protocol { } } +sub scan_wayland_protocol_from_file { + my $proto = $_[0]; + my $file = $_[1]; + my $proto_c = "src/backend/wayland/wayland-${proto}-protocol.c"; + + if ( + system( + "wayland-scanner private-code ./resource/wayland/${file} ${proto_c}" + ) != 0 + ) + { + print( + "^ Error on getting private code for ./resource/wayland/${file}\n"); + } + else { + new_object($proto_c); + } + if ( + system( +"wayland-scanner client-header ./resource/wayland/${file} include/Mw/LowLevel/Wayland/${proto}-client-protocol.h" + ) + ) + { + print( + "^ Error on getting client header for ./resource/wayland/${file}\n" + ); + } +} + our %params = (); sub param_set { diff --git a/resource/milsko.pc.in b/resource/milsko.pc.in new file mode 100644 index 0000000..9cdc61e --- /dev/null +++ b/resource/milsko.pc.in @@ -0,0 +1,10 @@ +prefix="@CMAKE_INSTALL_PREFIX@" +includedir="@CMAKE_INSTALL_PREFIX@/include" +libdir="@CMAKE_INSTALL_PREFIX@/bin" + +Name: @PROJECT_NAME@ +Description: @PROJECT_DESCRIPTION@ +URL: @PROJECT_HOMEPAGE_URL@ +Version: @PROJECT_VERSION@ +Cflags: -I"${includedir}"/ +Libs: -L"${libdir}" -lMw diff --git a/resource/wayland/wlr-layer-shell-unstable-v1.xml b/resource/wayland/wlr-layer-shell-unstable-v1.xml new file mode 100644 index 0000000..f9ee0ff --- /dev/null +++ b/resource/wayland/wlr-layer-shell-unstable-v1.xml @@ -0,0 +1,451 @@ + + + + Copyright © 2017 Drew DeVault + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + Clients can use this interface to assign the surface_layer role to + wl_surfaces. Such surfaces are assigned to a "layer" of the output and + rendered with a defined z-depth respective to each other. They may also be + anchored to the edges and corners of a screen and specify input handling + semantics. This interface should be suitable for the implementation of + many desktop shell components, and a broad number of other applications + that interact with the desktop. + + + + + Create a layer surface for an existing surface. This assigns the role of + layer_surface, or raises a protocol error if another role is already + assigned. + + Creating a layer surface from a wl_surface which has a buffer attached + or committed is a client error, and any attempts by a client to attach + or manipulate a buffer prior to the first layer_surface.configure call + must also be treated as errors. + + After creating a layer_surface object and setting it up, the client + must perform an initial commit without any buffer attached. + The compositor will reply with a layer_surface.configure event. + The client must acknowledge it and is then allowed to attach a buffer + to map the surface. + + You may pass NULL for output to allow the compositor to decide which + output to use. Generally this will be the one that the user most + recently interacted with. + + Clients can specify a namespace that defines the purpose of the layer + surface. + + + + + + + + + + + + + + + + + These values indicate which layers a surface can be rendered in. They + are ordered by z depth, bottom-most first. Traditional shell surfaces + will typically be rendered between the bottom and top layers. + Fullscreen shell surfaces are typically rendered at the top layer. + Multiple surfaces can share a single layer, and ordering within a + single layer is undefined. + + + + + + + + + + + + + This request indicates that the client will not use the layer_shell + object any more. Objects that have been created through this instance + are not affected. + + + + + + + An interface that may be implemented by a wl_surface, for surfaces that + are designed to be rendered as a layer of a stacked desktop-like + environment. + + Layer surface state (layer, size, anchor, exclusive zone, + margin, interactivity) is double-buffered, and will be applied at the + time wl_surface.commit of the corresponding wl_surface is called. + + Attaching a null buffer to a layer surface unmaps it. + + Unmapping a layer_surface means that the surface cannot be shown by the + compositor until it is explicitly mapped again. The layer_surface + returns to the state it had right after layer_shell.get_layer_surface. + The client can re-map the surface by performing a commit without any + buffer attached, waiting for a configure event and handling it as usual. + + + + + Sets the size of the surface in surface-local coordinates. The + compositor will display the surface centered with respect to its + anchors. + + If you pass 0 for either value, the compositor will assign it and + inform you of the assignment in the configure event. You must set your + anchor to opposite edges in the dimensions you omit; not doing so is a + protocol error. Both values are 0 by default. + + Size is double-buffered, see wl_surface.commit. + + + + + + + + Requests that the compositor anchor the surface to the specified edges + and corners. If two orthogonal edges are specified (e.g. 'top' and + 'left'), then the anchor point will be the intersection of the edges + (e.g. the top left corner of the output); otherwise the anchor point + will be centered on that edge, or in the center if none is specified. + + Anchor is double-buffered, see wl_surface.commit. + + + + + + + Requests that the compositor avoids occluding an area with other + surfaces. The compositor's use of this information is + implementation-dependent - do not assume that this region will not + actually be occluded. + + A positive value is only meaningful if the surface is anchored to one + edge or an edge and both perpendicular edges. If the surface is not + anchored, anchored to only two perpendicular edges (a corner), anchored + to only two parallel edges or anchored to all edges, a positive value + will be treated the same as zero. + + A positive zone is the distance from the edge in surface-local + coordinates to consider exclusive. + + Surfaces that do not wish to have an exclusive zone may instead specify + how they should interact with surfaces that do. If set to zero, the + surface indicates that it would like to be moved to avoid occluding + surfaces with a positive exclusive zone. If set to -1, the surface + indicates that it would not like to be moved to accommodate for other + surfaces, and the compositor should extend it all the way to the edges + it is anchored to. + + For example, a panel might set its exclusive zone to 10, so that + maximized shell surfaces are not shown on top of it. A notification + might set its exclusive zone to 0, so that it is moved to avoid + occluding the panel, but shell surfaces are shown underneath it. A + wallpaper or lock screen might set their exclusive zone to -1, so that + they stretch below or over the panel. + + The default value is 0. + + Exclusive zone is double-buffered, see wl_surface.commit. + + + + + + + Requests that the surface be placed some distance away from the anchor + point on the output, in surface-local coordinates. Setting this value + for edges you are not anchored to has no effect. + + The exclusive zone includes the margin. + + Margin is double-buffered, see wl_surface.commit. + + + + + + + + + + Types of keyboard interaction possible for layer shell surfaces. The + rationale for this is twofold: (1) some applications are not interested + in keyboard events and not allowing them to be focused can improve the + desktop experience; (2) some applications will want to take exclusive + keyboard focus. + + + + + This value indicates that this surface is not interested in keyboard + events and the compositor should never assign it the keyboard focus. + + This is the default value, set for newly created layer shell surfaces. + + This is useful for e.g. desktop widgets that display information or + only have interaction with non-keyboard input devices. + + + + + Request exclusive keyboard focus if this surface is above the shell surface layer. + + For the top and overlay layers, the seat will always give + exclusive keyboard focus to the top-most layer which has keyboard + interactivity set to exclusive. If this layer contains multiple + surfaces with keyboard interactivity set to exclusive, the compositor + determines the one receiving keyboard events in an implementation- + defined manner. In this case, no guarantee is made when this surface + will receive keyboard focus (if ever). + + For the bottom and background layers, the compositor is allowed to use + normal focus semantics. + + This setting is mainly intended for applications that need to ensure + they receive all keyboard events, such as a lock screen or a password + prompt. + + + + + This requests the compositor to allow this surface to be focused and + unfocused by the user in an implementation-defined manner. The user + should be able to unfocus this surface even regardless of the layer + it is on. + + Typically, the compositor will want to use its normal mechanism to + manage keyboard focus between layer shell surfaces with this setting + and regular toplevels on the desktop layer (e.g. click to focus). + Nevertheless, it is possible for a compositor to require a special + interaction to focus or unfocus layer shell surfaces (e.g. requiring + a click even if focus follows the mouse normally, or providing a + keybinding to switch focus between layers). + + This setting is mainly intended for desktop shell components (e.g. + panels) that allow keyboard interaction. Using this option can allow + implementing a desktop shell that can be fully usable without the + mouse. + + + + + + + Set how keyboard events are delivered to this surface. By default, + layer shell surfaces do not receive keyboard events; this request can + be used to change this. + + This setting is inherited by child surfaces set by the get_popup + request. + + Layer surfaces receive pointer, touch, and tablet events normally. If + you do not want to receive them, set the input region on your surface + to an empty region. + + Keyboard interactivity is double-buffered, see wl_surface.commit. + + + + + + + This assigns an xdg_popup's parent to this layer_surface. This popup + should have been created via xdg_surface::get_popup with the parent set + to NULL, and this request must be invoked before committing the popup's + initial state. + + See the documentation of xdg_popup for more details about what an + xdg_popup is and how it is used. + + + + + + + When a configure event is received, if a client commits the + surface in response to the configure event, then the client + must make an ack_configure request sometime before the commit + request, passing along the serial of the configure event. + + If the client receives multiple configure events before it + can respond to one, it only has to ack the last configure event. + + A client is not required to commit immediately after sending + an ack_configure request - it may even ack_configure several times + before its next surface commit. + + A client may send multiple ack_configure requests before committing, but + only the last request sent before a commit indicates which configure + event the client really is responding to. + + + + + + + This request destroys the layer surface. + + + + + + The configure event asks the client to resize its surface. + + Clients should arrange their surface for the new states, and then send + an ack_configure request with the serial sent in this configure event at + some point before committing the new surface. + + The client is free to dismiss all but the last configure event it + received. + + The width and height arguments specify the size of the window in + surface-local coordinates. + + The size is a hint, in the sense that the client is free to ignore it if + it doesn't resize, pick a smaller size (to satisfy aspect ratio or + resize in steps of NxM pixels). If the client picks a smaller size and + is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the + surface will be centered on this axis. + + If the width or height arguments are zero, it means the client should + decide its own window dimension. + + + + + + + + + The closed event is sent by the compositor when the surface will no + longer be shown. The output may have been destroyed or the user may + have asked for it to be removed. Further changes to the surface will be + ignored. The client should destroy the resource after receiving this + event, and create a new surface if they so choose. + + + + + + + + + + + + + + + + + + + + + + Change the layer that the surface is rendered on. + + Layer is double-buffered, see wl_surface.commit. + + + + + diff --git a/src/abstract/charset.c b/src/abstract/charset.c index 3620aa0..3bd7625 100644 --- a/src/abstract/charset.c +++ b/src/abstract/charset.c @@ -19,7 +19,7 @@ char* MwACPToUTF8(const char* input) { return MwStringDuplicate(input); } - wout = malloc(wbytes); + wout = malloc(wbytes + sizeof(wchar_t)); len = wbytes / sizeof(wchar_t); memset(wout, 0, wbytes); @@ -64,7 +64,7 @@ char* MwUTF8ToACP(const char* input) { return MwStringDuplicate(input); } - wout = malloc(wbytes); + wout = malloc(wbytes + sizeof(wchar_t)); len = wbytes / sizeof(wchar_t); memset(wout, 0, wbytes); diff --git a/src/abstract/directory.c b/src/abstract/directory.c index ac5a382..ddf10e1 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -19,15 +19,19 @@ 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, "\\"); + char * p; + if(!dir) { + printf("Out Of Memory\n"); + return NULL; } - strcat(p, "*"); +#ifdef _WIN32 + 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); @@ -66,8 +70,19 @@ 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 stat s; + char* p; +#endif + + if(!entry) { + printf("Out Of Memory\n"); + return NULL; + } +#ifdef _WIN32 if(!dir->next) return NULL; entry->name = MwStringDuplicate(dir->ffd.cFileName); @@ -91,9 +106,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; @@ -170,8 +182,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 +199,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/abstract/time.c b/src/abstract/time.c index d1ddb83..892cd32 100644 --- a/src/abstract/time.c +++ b/src/abstract/time.c @@ -2,7 +2,7 @@ #if defined(_WIN32) long MwTimeGetTick(void) { - return GetTickCount(); + return MwLL_PFN_timeGetTime(); } void MwTimeSleep(int ms) { diff --git a/src/backend/cairo.c b/src/backend/cairo.c new file mode 100644 index 0000000..65380fb --- /dev/null +++ b/src/backend/cairo.c @@ -0,0 +1,266 @@ +#include + +#include "../../external/stb_ds.h" + +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); + for(i = 0; i < points_count; i++) { + if(i == 0) { + cairo_move_to(handle.front_cairo, points[i].x, points[i].y); + } else { + cairo_line_to(handle.front_cairo, points[i].x, points[i].y); + } + } + cairo_close_path(handle.front_cairo); + + cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_SOURCE); + cairo_fill(handle.front_cairo); + cairo_set_operator(handle.front_cairo, 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); + for(i = 0; i < 2; i++) { + if(i == 0) { + cairo_move_to(handle.front_cairo, points[i].x, points[i].y); + } else { + cairo_line_to(handle.front_cairo, points[i].x, points[i].y); + } + } + cairo_close_path(handle.front_cairo); + cairo_stroke(handle.front_cairo); +}; + +MwLLPixmap MwLLCairoCreatePixmap(struct _MwLLCairo handle, unsigned char* data, int width, int height) { + MwLLPixmap r = malloc(sizeof(*r)); + (void)handle; + + if(width >= INT16_MAX) width = INT16_MAX; + if(height >= INT16_MAX) height = INT16_MAX; + + r->common.width = width; + r->common.height = height; + r->common.raw = malloc(4 * width * height); + memcpy(r->common.raw, data, 4 * width * height); + + r->wayland.cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + + MwLLPixmapUpdate(r); + + return r; +} + +void MwLLCairoPixmapUpdate(MwLLPixmap r) { + int i; + unsigned char* d; + + cairo_surface_flush(r->wayland.cs); + d = cairo_image_surface_get_data(r->wayland.cs); + for(i = 0; i < r->common.width * r->common.height * 4; i += 4) { + MwU32* p = (MwU32*)&d[i]; + *p <<= 8; + *p |= r->common.raw[i + 3]; + *p <<= 8; + *p |= r->common.raw[i + 0]; + *p <<= 8; + *p |= r->common.raw[i + 1]; + *p <<= 8; + *p |= r->common.raw[i + 2]; + } + cairo_surface_mark_dirty(r->wayland.cs); +} + +void MwLLCairoDestroyPixmap(MwLLPixmap pixmap) { + cairo_surface_destroy(pixmap->wayland.cs); + free(pixmap->common.raw); + free(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; + cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); + c = cairo_create(cs); + + if(rect->width <= 0 || rect->height <= 0 || pixmap->common.width <= 0 || pixmap->common.height <= 0) return; + if(rect->width >= INT16_MAX) rect->width = INT16_MAX; + if(rect->height >= INT16_MAX) rect->height = INT16_MAX; + + cairo_scale(c, (double)rect->width / pixmap->common.width, (double)rect->height / pixmap->common.height); + + 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_paint(c); + + cairo_set_source_surface(selected_cairo, cs, rect->x, rect->y); + cairo_paint(selected_cairo); + + cairo_destroy(c); + cairo_surface_destroy(cs); +}; + +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); + } else { + cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + } + cairo->front_cairo = cairo_create(cairo->front_cs); +} + +void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) { + if(data) { + cairo->back_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4); + } else { + cairo->back_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + } + cairo->back_cairo = cairo_create(cairo->back_cs); +} + +void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) { + cairo_destroy(cairo->front_cairo); + cairo_surface_destroy(cairo->front_cs); +}; +void MwLLCairoBackDestroy(struct _MwLLCairo* cairo) { + cairo_destroy(cairo->back_cairo); + cairo_surface_destroy(cairo->back_cs); +}; + +void MwLLCairoDestroy(struct _MwLLCairo handle) { + // MwLLCairoFrontDestroy(&handle); + // MwLLCairoBackDestroy(&handle); +} + +static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { + MwLL r; + r = malloc(sizeof(*r)); + memset(r, 0, sizeof(*r)); + MwLLCreateCommon(r); + + r->cairo.width = width; + r->cairo.height = height; + r->cairo.x = x; + r->cairo.y = x; + + r->cairo.toplevel = !parent; + r->cairo.parent = parent; + + MwLLCairoFrontSetup(&r->cairo, NULL, r->cairo.width, r->cairo.height); + MwLLCairoBackSetup(&r->cairo, NULL, r->cairo.width, r->cairo.height); + + return r; +} +static void MwLLDestroyImpl(MwLL handle) { + MwLLCairoDestroy(handle->cairo); + free(handle); +} + +static void MwLLBeginDrawImpl(MwLL handle) { + handle->cairo.selected_cairo = handle->cairo.front_cairo; +} +static void MwLLEndDrawImpl(MwLL handle) { +} + +static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { + MwLLCairoPolygon(handle->cairo, points, points_count, color); +} +static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { + MwLLCairoLine(handle->cairo, points, color); +} +static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { + MwLLColor c = malloc(sizeof(*c)); + MwLLColorUpdate(handle, c, r, g, b); + return c; +} + +static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { + (void)handle; + + c->common.red = r; + c->common.green = g; + c->common.blue = b; +} +static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { + (void)handle; + *x = handle->cairo.x; + *y = handle->cairo.y; + *w = handle->cairo.width; + *h = handle->cairo.height; +} +static void MwLLSetXYImpl(MwLL handle, int x, int y) { + handle->cairo.x = x; + handle->cairo.y = y; +} +static void MwLLSetWHImpl(MwLL handle, int w, int h) { + handle->cairo.width = w; + handle->cairo.height = h; +} +static void MwLLFreeColorImpl(MwLLColor color) {} + +static MwBool lmao = MwFALSE; +static int MwLLPendingImpl(MwLL handle) { + lmao = !lmao; + return lmao; +} +static void MwLLNextEventImpl(MwLL handle) { + MwLLDispatch(handle, draw, NULL); +} +static void MwLLSetTitleImpl(MwLL handle, const char* title) {} +static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { + return MwLLCairoCreatePixmap(handle->cairo, data, width, height); +} +static void MwLLPixmapUpdateImpl(MwLLPixmap r) { + MwLLCairoPixmapUpdate(r); +} +static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { + MwLLCairoPixmapUpdate(pixmap); +} + +static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { + MwLLCairoDrawPixmap(handle->cairo, rect, pixmap); +} +static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {} +static void MwLLForceRenderImpl(MwLL handle) {} +static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) {} +static void MwLLDetachImpl(MwLL handle, MwPoint* point) {} +static void MwLLShowImpl(MwLL handle, int show) {} +static void MwLLMakePopupImpl(MwLL handle, MwLL parent) {} +static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) {} +static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) {} +static void MwLLFocusImpl(MwLL handle) {} +static void MwLLGrabPointerImpl(MwLL handle, int toggle) {} +static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) {} +static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {} +static void MwLLMakeToolWindowImpl(MwLL handle) {} +static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) {} +static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) {} +static void MwLLBeginStateChangeImpl(MwLL handle) {} +static void MwLLEndStateChangeImpl(MwLL handle) {} +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) {} +static MwBool MwLLDoModernImpl(MwLL handle) { + return MwFALSE; +} +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; +} +#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 fb2549e..f063551 100644 --- a/src/backend/classicmacos.c +++ b/src/backend/classicmacos.c @@ -1,6 +1,5 @@ #include #include -#include #include "../../external/stb_ds.h" @@ -53,9 +52,6 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL col.green = color->common.green * 0x101; col.blue = color->common.blue * 0x101; - RGBForeColor(&col); - PenMode(patCopy); - for(i = 0; i < points_count; i++) { if(i == 0) { MoveTo(points[i].x, points[i].y); @@ -65,7 +61,11 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL } ClosePoly(); - FillCPoly(p, &qd.ltGray); + + PenMode(patCopy); + RGBForeColor(&col); + PaintPoly(p); + KillPoly(p); EndUpdate(handle->cmacos.window); @@ -132,9 +132,23 @@ static void MwLLNextEventImpl(MwLL handle) { switch(event.what) { case updateEvt: { - } - // MwLLDispatch(handle, draw, NULL); - break; + /* + This is our blocker for getting anything running. + This needs to be called at this point to start drawing anything. + ...It locks up and/or crashes the entire system. At least on SheepShaver. + It's not a stack overflow, it's not anything in the drawing functions. + It's *something* else. But because Classic Mac OS development is like + digging up forbidden tombs while stabbing yourself in the eye several times, + I don't know what. + + Fun fact: for as much as everyone loves to glaze about AI being the future + of programming, even Claude got confused when I gave up and tried to ask it + for help. Information about Classic Mac OS probably takes up 0.0001% of its + knowledge base; god knows it's hard enough finding information online about + this! + */ + MwLLDispatch(handle, draw, NULL); + } break; case osEvt: break; case mouseUp: @@ -333,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 bbab256..eace1d3 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,14 @@ typedef struct userdata { static struct symtbl { void* lib_dwmapi; + void* shell32lib; + 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); + void (*DragAcceptFiles)(HWND hWnd, BOOL fAccept); + void (*DragFinish)(HDROP hDrop); } wsymtbl; static int is_plgblt_reliable = 0; @@ -67,7 +75,11 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { if(u == NULL) return DefWindowProc(hWnd, msg, wp, lp); - if(msg == WM_PAINT) { + switch(msg) { + case WM_INITDIALOG: + return TRUE; + case WM_PAINT: + { PAINTSTRUCT ps; RECT rc; HBITMAP hbmp; @@ -98,7 +110,12 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { MwLLDispatch(u->ll, draw, NULL); EndPaint(hWnd, &ps); } - } else if(msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN || msg == WM_RBUTTONDOWN) { + break; + } + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + { MwMouse p; p.point.x = LOWORD(lp); p.point.y = HIWORD(lp); @@ -113,7 +130,12 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { SetCapture(hWnd); SetFocus(hWnd); MwLLDispatch(u->ll, down, &p); - } else if(msg == WM_LBUTTONUP || msg == WM_MBUTTONUP || msg == WM_RBUTTONUP) { + break; + } + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + { MwMouse p; p.point.x = LOWORD(lp); p.point.y = HIWORD(lp); @@ -127,7 +149,10 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { SetCapture(NULL); MwLLDispatch(u->ll, up, &p); - } else if(msg == WM_MOUSEWHEEL) { + break; + } + case WM_MOUSEWHEEL: + { int d = GET_WHEEL_DELTA_WPARAM(wp); MwMouse p; p.point.x = LOWORD(lp); @@ -141,7 +166,31 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { MwLLDispatch(u->ll, down, &p); MwLLDispatch(u->ll, up, &p); - } else if(msg == WM_MOUSEMOVE) { + break; + } + case WM_DROPFILES: + { + HDROP hDrop = (HDROP)wp; + UINT count; + UINT i; + + 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); + + 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); + break; + } + case WM_MOUSEMOVE: + { MwPoint p; p.x = LOWORD(lp); p.y = HIWORD(lp); @@ -169,19 +218,37 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { SetCursorPos(p.x, p.y); } - } else if(msg == WM_SIZE) { + + break; + } + case WM_SIZE: + { MwLLDispatch(u->ll, resize, NULL); - } else if(msg == WM_ERASEBKGND) { + break; + } + case WM_ERASEBKGND: + { return 1; - } else if(msg == WM_NCHITTEST) { + } + case WM_NCHITTEST: + { LPARAM style = GetWindowLongPtr(hWnd, GWL_STYLE); if(style & WS_CHILD) return HTCLIENT; return DefWindowProc(hWnd, msg, wp, lp); - } else if(msg == WM_DESTROY) { + } + case WM_DESTROY: + { PostQuitMessage(0); - } else if(msg == WM_CLOSE) { + break; + } + case WM_CLOSE: + { MwLLDispatch(u->ll, close, NULL); - } else if(msg == WM_CHAR || msg == WM_SYSCHAR) { + break; + } + case WM_CHAR: + case WM_SYSCHAR: + { int n = wp; const int base = 'A' - 1; @@ -193,24 +260,61 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { if(msg == WM_SYSCHAR) n |= MwKEY_ALT_FLAG; if((0x20 <= n && n <= 0x7f) || (n & MwKEY_FLAG)) MwLLDispatch(u->ll, key, &n); - } else if(msg == WM_SETFOCUS) { + break; + } + case WM_SETFOCUS: + { MwLLDispatch(u->ll, focus_in, NULL); - } else if(msg == WM_KILLFOCUS) { + break; + } + case WM_KILLFOCUS: + { MwLLDispatch(u->ll, focus_out, NULL); - } else if(msg == WM_KEYDOWN || msg == WM_KEYUP || msg == WM_SYSKEYDOWN || msg == WM_SYSKEYUP) { + break; + } + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + { int n = -1; + if(wp == VK_MENU && msg == WM_KEYUP) return 0; - if(wp == VK_LEFT) n = MwKEY_LEFT; - if(wp == VK_RIGHT) n = MwKEY_RIGHT; - if(wp == VK_UP) n = MwKEY_UP; - if(wp == VK_DOWN) n = MwKEY_DOWN; - if(wp == VK_RETURN) n = MwKEY_ENTER; - if(wp == VK_BACK) n = MwKEY_BACKSPACE; - if(wp == VK_ESCAPE) n = MwKEY_ESCAPE; - if(wp == VK_LSHIFT) n = MwKEY_LEFTSHIFT; - if(wp == VK_RSHIFT) n = MwKEY_RIGHTSHIFT; - if(wp == VK_MENU) n = MwKEY_ALT; - if(wp == VK_CONTROL) n = MwKEY_CONTROL; + switch(wp) { + case VK_LEFT: + n = MwKEY_LEFT; + break; + case VK_RIGHT: + n = MwKEY_RIGHT; + break; + case VK_UP: + n = MwKEY_UP; + break; + case VK_DOWN: + n = MwKEY_DOWN; + break; + case VK_RETURN: + n = MwKEY_ENTER; + break; + case VK_BACK: + n = MwKEY_BACKSPACE; + break; + case VK_ESCAPE: + n = MwKEY_ESCAPE; + break; + case VK_LSHIFT: + n = MwKEY_LEFTSHIFT; + break; + case VK_RSHIFT: + n = MwKEY_RIGHTSHIFT; + break; + case VK_MENU: + n = MwKEY_ALT; + break; + case VK_CONTROL: + n = MwKEY_CONTROL; + break; + } if((msg == WM_SYSKEYDOWN || msg == WM_SYSKEYUP) && n != -1 && wp != VK_MENU) { n |= MwKEY_ALT_FLAG; @@ -222,7 +326,10 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { MwLLDispatch(u->ll, key_released, &n); } } - } else if(msg == WM_GETMINMAXINFO) { + break; + } + case WM_GETMINMAXINFO: + { if(u->min_set || u->max_set) { LPARAM style = GetWindowLongPtr(hWnd, GWL_STYLE); MINMAXINFO* mmi = (MINMAXINFO*)lp; @@ -253,22 +360,35 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { } else { return DefWindowProc(hWnd, msg, wp, lp); } - } else if(msg == WM_SETCURSOR) { + break; + } + case WM_SETCURSOR: + { if(LOWORD(lp) != HTCLIENT) return DefWindowProc(hWnd, msg, wp, lp); if(u->ll->gdi.cursor != NULL) SetCursor(u->ll->gdi.cursor); - } else if(msg == WM_USER) { + break; + } + case WM_USER: + { InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); - } else if(msg == WM_WININICHANGE) { + break; + } + case WM_WININICHANGE: + { char* s = (char*)lp; LPARAM style = GetWindowLongPtr(hWnd, GWL_STYLE); if(!(style & WS_CHILD)) { if(s != NULL && strcmp(s, "ImmersiveColorSet") == 0) detect_darktheme(u->ll); } - } else { + break; + } + default: + { return DefWindowProc(hWnd, msg, wp, lp); } + } return 0; } @@ -277,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; @@ -362,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; @@ -396,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); @@ -404,7 +539,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; @@ -413,8 +549,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.brush = CreateSolidBrush(GetNearestColor(dc, RGB(r, g, b))); + c->gdi.brush = CreateSolidBrush(color); c->common.red = r; c->common.green = g; c->common.blue = b; @@ -470,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(); @@ -490,10 +638,11 @@ 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); - TranslateMessage(&msg); - DispatchMessage(&msg); + while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { + if(GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } } @@ -502,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; @@ -542,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++) { @@ -793,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); @@ -905,6 +1088,10 @@ static void MwLLClipImpl(MwLL handle, MwRect* rect) { } } +static void MwLLSetupDragAndDropImpl(MwLL handle) { + wsymtbl.DragAcceptFiles(handle->gdi.hWnd, TRUE); +} + static int MwLLGDICallInitImpl(void) { void* ntdll; @@ -920,6 +1107,28 @@ static int MwLLGDICallInitImpl(void) { is_plgblt_reliable = 1; } + wsymtbl.has_drag_and_drop = MwFALSE; + + /* Drag and Drop initialization */ + { + if(!(wsymtbl.shell32lib = LoadLibrary("shell32.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; \ + } + + SHELL32_FUNC(DragQueryFileW); + SHELL32_FUNC(DragAcceptFiles); + SHELL32_FUNC(DragFinish); + + 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/buffer.c b/src/backend/wayland/buffer.c index a37fd34..df1de79 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -4,8 +4,7 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh); - wayland->front_cs = cairo_image_surface_create_for_data(wayland->framebuffer.buf_back, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww); - wayland->front_cairo = cairo_create(wayland->front_cs); + MwLLCairoFrontSetup(&wayland->cairo, wayland->framebuffer.buf_back, wayland->ww, wayland->wh); memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size); if(wayland->configured) @@ -16,9 +15,9 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->framebuffer); }; void MwLLWaylandFramebufferDestroy(struct _MwLLWayland* wayland) { + wl_surface_attach(wayland->framebuffer.surface, NULL, 0, 0); MwLLWaylandBufferDestroy(&wayland->framebuffer); - cairo_destroy(wayland->front_cairo); - cairo_surface_destroy(wayland->front_cs); + MwLLCairoFrontDestroy(&wayland->cairo); }; void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) { @@ -27,14 +26,13 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) { } MwU32 w = wayland->ww; MwU32 h = wayland->wh; - if(!wayland->has_decorations) { + 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); } MwLLWaylandBufferSetup(&wayland->backbuffer, w, h); - wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf_back, CAIRO_FORMAT_ARGB32, w, h, 4 * w); - wayland->back_cairo = cairo_create(wayland->back_cs); + MwLLCairoBackSetup(&wayland->cairo, wayland->backbuffer.buf_back, w, h); memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size); if(wayland->configured) @@ -44,9 +42,9 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) { MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->backbuffer); }; void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* wayland) { + // wl_surface_attach(wayland->backbuffer.surface, NULL, 0, 0); MwLLWaylandBufferDestroy(&wayland->backbuffer); - cairo_destroy(wayland->back_cairo); - cairo_surface_destroy(wayland->back_cs); + MwLLCairoBackDestroy(&wayland->cairo); }; void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index fa64268..84ed492 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -16,6 +16,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); + /* 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; @@ -42,7 +45,7 @@ static void new_protocol(void* data, struct wl_registry* registry, 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)); + 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) { self->common.supports_transparency = MwTRUE; @@ -313,7 +316,8 @@ 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) { +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_source.wl = wl_data_device_manager_create_data_source(wayland->clipboard_manager.wl); @@ -346,7 +350,8 @@ static void wl_data_device_manager_interface_destroy(struct _MwLLWayland* waylan } /* zwp_primary_selection_device_manager_v1 setup function */ -static wayland_protocol_t* zwp_primary_selection_device_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* zwp_primary_selection_device_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + (void)version; wayland->clipboard_manager.zwp = wl_registry_bind(wayland->registry, name, &zwp_primary_selection_device_manager_v1_interface, 1); wayland->clipboard_source.zwp = zwp_primary_selection_device_manager_v1_create_source(wayland->clipboard_manager.zwp); @@ -374,7 +379,8 @@ static void zwp_primary_selection_device_manager_v1_interface_destroy(struct _Mw } /* zwp_primary_selection_device_manager_v1 setup function */ -static wayland_protocol_t* zwp_pointer_constraints_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* zwp_pointer_constraints_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + (void)version; wayland->pointer_constraints = wl_registry_bind(wayland->registry, name, &zwp_pointer_constraints_v1_interface, 1); return NULL; } @@ -406,6 +412,10 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, topmost_parent->wayland.cursor.surface, 0, 0); } + + if(self->wayland.backbuffer.surface == surface) { + curSurface = surface; + } WAYLAND_EVENT_OP_END(self); }; @@ -421,7 +431,7 @@ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 seria WAYLAND_EVENT_OP_END(self); }; -static void xdg_borderless_step(MwLL self, MwMouse p, MwU32 serial) { +static void xdg_borderless_step_mdown(MwLL self, MwMouse p, MwU32 serial) { if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.backbuffer.surface == curSurface) { if(p.point.y >= (self->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM) - 5) { if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 5) { @@ -440,7 +450,33 @@ static void xdg_borderless_step(MwLL self, MwMouse p, MwU32 serial) { } else if(p.point.x <= 5) { xdg_toplevel_resize(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial, XDG_TOPLEVEL_RESIZE_EDGE_LEFT); } else if(p.point.y <= CSD_BORDER_FRAME_TOP) { - xdg_toplevel_move(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial); + if(p.point.x >= CSD_BORDER_FRAME_LEFT && p.point.x <= CSD_BORDER_FRAME_LEFT + 18) { + } else if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 21) { + } else if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 38) { + } else { + xdg_toplevel_move(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial); + } + } + }; +} +static void xdg_borderless_step_mup(MwLL self, MwMouse p, MwU32 serial) { + (void)serial; + if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.backbuffer.surface == curSurface) { + if(p.point.y <= CSD_BORDER_FRAME_TOP) { + if(p.point.x >= CSD_BORDER_FRAME_LEFT && p.point.x <= CSD_BORDER_FRAME_LEFT + 18) { + MwLLDispatch(self, close, NULL); + } else if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 21) { + self->wayland.toplevel->maxim_state = !self->wayland.toplevel->maxim_state; + if(self->wayland.toplevel->maxim_state == 0) { + xdg_toplevel_unset_maximized(self->wayland.toplevel->xdg_top_level); + } else { + xdg_toplevel_set_maximized(self->wayland.toplevel->xdg_top_level); + } + self->wayland.setting_wh = 1; + MwLLWaylandRegionSetup(self); + } else if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 38) { + xdg_toplevel_set_minimized(self->wayland.toplevel->xdg_top_level); + } } }; } @@ -478,7 +514,8 @@ struct zwp_relative_pointer_v1_listener MwLLWaylandRelativePointerListener = relative_pointer_motion}; /* zwp_primary_selection_device_manager_v1 setup function */ -static wayland_protocol_t* zwp_relative_pointer_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* zwp_relative_pointer_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + (void)version; wayland->relative_pointer_manager = wl_registry_bind(wayland->registry, name, &zwp_relative_pointer_manager_v1_interface, 1); return NULL; } @@ -571,6 +608,9 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri 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; @@ -586,8 +626,11 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri } } - if(!self->wayland.has_decorations) { - xdg_borderless_step(self, p, serial); + 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); } WAYLAND_EVENT_OP_END(self); @@ -620,7 +663,7 @@ static void keyboard_keymap(void* data, MwLL self = data; (void)wl_keyboard; - if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL) { + if(!self->wayland.parent) { assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1); char* map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); @@ -683,15 +726,18 @@ static void keyboard_leave(void* data, static void keyboard_key(void* data, struct wl_keyboard* wl_keyboard, MwU32 serial, - MwU32 time, + MwU32 _time, MwU32 key, MwU32 state) { - MwLL self = data; - MwBool inArea = 0; + MwLL self = data; + MwBool inArea = 0; + MwLL topmost_parent = self; (void)wl_keyboard; (void)serial; - (void)time; + (void)_time; + + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; WAYLAND_EVENT_OP_START(self); @@ -702,6 +748,9 @@ static void keyboard_key(void* data, 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; @@ -791,9 +840,14 @@ static void keyboard_key(void* data, MwLLDispatch(topmost_parent, key, &key); topmost_parent = topmost_parent->wayland.parent; } + self->wayland.holding_key = MwTRUE; + self->wayland.last_pressed_key = key; } else { MwLLDispatch(self, key_released, &key); + self->wayland.holding_key = MwFALSE; } + self->wayland.start_time = MwTimeGetTick(); + self->wayland.next_elapsed = self->wayland.keyboard_delay; } } } @@ -848,12 +902,25 @@ static void setup_clipboard(MwLL self, struct wl_seat* wl_seat) { arrpush(self->wayland.clipboard_devices_wl, device_ctx_wl); }; +static void keyboard_repeat_info(void* data, + struct wl_keyboard* wl_keyboard, + int32_t rate, + int32_t delay) { + MwLL self = data; + + (void)wl_keyboard; + + self->wayland.keyboard_rate = rate; + self->wayland.keyboard_delay = delay; +}; + struct wl_keyboard_listener keyboard_listener = { - .keymap = keyboard_keymap, - .enter = keyboard_enter, - .leave = keyboard_leave, - .key = keyboard_key, - .modifiers = keyboard_modifiers, + .keymap = keyboard_keymap, + .enter = keyboard_enter, + .leave = keyboard_leave, + .key = keyboard_key, + .modifiers = keyboard_modifiers, + .repeat_info = keyboard_repeat_info, }; /* `wl_seat.name` callback */ @@ -937,14 +1004,15 @@ void xdg_wm_base_ping(void* data, }; /* wl_seat setup function */ -static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) { +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; proto->listener = malloc(sizeof(struct wl_seat_listener)); ((struct wl_seat_listener*)proto->listener)->name = wl_seat_name; ((struct wl_seat_listener*)proto->listener)->capabilities = wl_seat_capabilities; - wl_seat_add_listener(wl_registry_bind(ll->wayland.registry, name, &wl_seat_interface, 1), proto->listener, ll); + wl_seat_add_listener(wl_registry_bind(ll->wayland.registry, name, &wl_seat_interface, ver), proto->listener, ll); return proto; } @@ -952,10 +1020,12 @@ static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) { static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { (void)wayland; free(data->listener); + free(data); } /* wl_output setup function */ -static wayland_protocol_t* wl_output_setup(MwU32 name, MwLL ll) { +static wayland_protocol_t* wl_output_setup(MwU32 name, MwLL ll, MwU32 version) { + (void)version; ll->wayland.output = wl_registry_bind(ll->wayland.registry, name, &wl_output_interface, 1); wl_output_add_listener(ll->wayland.output, &output_listener, ll); @@ -968,7 +1038,8 @@ static void wl_output_interface_destroy(struct _MwLLWayland* wayland, wayland_pr } /* wl_compositor setup function */ -static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + (void)version; wayland->compositor = wl_registry_bind(wayland->registry, name, &wl_compositor_interface, 1); return NULL; @@ -980,7 +1051,8 @@ static void wl_compositor_interface_destroy(struct _MwLLWayland* wayland, waylan } /* wl_subcompositor setup function */ -static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + (void)version; if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } else { @@ -992,13 +1064,18 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { (void)data; - wl_subcompositor_destroy(wayland->sublevel->subcompositor); + if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { + wl_subcompositor_destroy(wayland->toplevel->scompositor); + } else { + wl_subcompositor_destroy(wayland->sublevel->subcompositor); + } } /* xdg_wm_base setup function */ -static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); - proto->listener = malloc(sizeof(struct xdg_wm_base_listener)); + (void)version; + proto->listener = malloc(sizeof(struct xdg_wm_base_listener)); ((struct xdg_wm_base_listener*)proto->listener)->ping = xdg_wm_base_ping; @@ -1011,12 +1088,14 @@ static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wa static void xdg_wm_base_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { (void)wayland; free(data->listener); + free(data); } /* xdg_wm_base setup function */ -static wayland_protocol_t* wp_viewporter_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wp_viewporter_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_viewporter_interface, 1); + (void)version; + proto->context = wl_registry_bind(wayland->registry, name, &wp_viewporter_interface, 1); return proto; } @@ -1027,10 +1106,11 @@ static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, waylan } /* zxdg_decoration_manager_v1 setup function */ -static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +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)); zxdg_decoration_manager_v1_context_t* ctx = malloc(sizeof(zxdg_decoration_manager_v1_context_t)); - proto->listener = NULL; + (void)version; + proto->listener = NULL; ctx->manager = wl_registry_bind(wayland->registry, name, &zxdg_decoration_manager_v1_interface, 1); ; @@ -1046,7 +1126,8 @@ static void zxdg_decoration_manager_v1_interface_destroy(struct _MwLLWayland* wa } /* wl_shm setup function */ -static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + (void)version; wayland->framebuffer.shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); wayland->backbuffer.shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); wayland->cursor.shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); @@ -1059,9 +1140,11 @@ static void wl_shm_interface_destroy(struct _MwLLWayland* wayland, wayland_proto (void)data; } -static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* xdg_toplevel_icon_manager_v1_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, &xdg_toplevel_icon_manager_v1_interface, 1); proto->listener = NULL; @@ -1071,6 +1154,22 @@ static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct static void xdg_toplevel_icon_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { (void)wayland; free(data->listener); + free(data); +} + +static wayland_protocol_t* zwlr_layer_shell_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, &zwlr_layer_shell_v1_interface, version); + proto->listener = NULL; + + return proto; +} + +static void zwlr_layer_shell_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. */ @@ -1086,8 +1185,16 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { wayland->registry_listener.global = new_protocol; wayland->registry_listener.global_remove = protocol_removed; - wayland->wl_protocol_setup_map = NULL; - wayland->wl_protocol_map = NULL; + + if(wayland->wl_protocol_map) { + shfree(wayland->wl_protocol_map); + } + if(wayland->wl_protocol_setup_map) { + shfree(wayland->wl_protocol_setup_map); + } + + wayland->wl_protocol_setup_map = NULL; + wayland->wl_protocol_map = NULL; sh_new_arena(wayland->wl_protocol_map); sh_new_arena(wayland->wl_protocol_setup_map); @@ -1101,12 +1208,16 @@ 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(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); } else if(wayland->type == MwLL_WAYLAND_POPUP) { + } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { + WL_INTERFACE(wp_viewporter); + WL_INTERFACE(wl_subcompositor); } else { WL_INTERFACE(wl_subcompositor); } diff --git a/src/backend/wayland/region.c b/src/backend/wayland/region.c index 207fa59..4b6a5ae 100644 --- a/src/backend/wayland/region.c +++ b/src/backend/wayland/region.c @@ -7,10 +7,13 @@ void MwLLWaylandRegionInvalidate(MwLL handle) { wl_region_subtract(handle->wayland.region, 0, 0, handle->wayland.ww, handle->wayland.wh); } void MwLLWaylandRegionSetup(MwLL handle) { - MwLL parent = handle->wayland.parent; - int width = (handle->wayland.clipping_rect.width == 0) ? handle->wayland.ww : handle->wayland.clipping_rect.width; - int height = (handle->wayland.clipping_rect.height == 0) ? handle->wayland.wh : handle->wayland.clipping_rect.height; + int width = (handle->wayland.clipping_rect.width == 0) ? handle->wayland.ww : handle->wayland.clipping_rect.width; + int height = (handle->wayland.clipping_rect.height == 0) ? handle->wayland.wh : handle->wayland.clipping_rect.height; + if(!handle->wayland.has_decorations && handle->wayland.do_csd && handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { + width += CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT; + height += CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM; + } if(!handle->wayland.configured) { return; } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 3d61932..839e9ac 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -10,11 +10,13 @@ wayland_call_table_t wl_call_tbl; MwBool MwWaylandVulkan = MwFALSE; #endif +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. * - * TODO(IOI): FUCKING NO???? FIX THIS. + * 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; @@ -126,9 +128,11 @@ static int event_loop(MwLL handle) { if(!poll(&fd, 1, timeout.tv_nsec)) { wl_display_cancel_read(wayland->display); - MwLLWaylandBufferUpdate(handle, &wayland->framebuffer); - if(wayland->type == MwLL_WAYLAND_TOPLEVEL) - MwLLWaylandBufferUpdate(handle, &wayland->backbuffer); + if(wayland->configured) { + MwLLWaylandBufferUpdate(handle, &wayland->framebuffer); + if(wayland->type == MwLL_WAYLAND_TOPLEVEL) + MwLLWaylandBufferUpdate(handle, &wayland->backbuffer); + } return 0; } wl_display_read_events(wayland->display); @@ -173,9 +177,20 @@ static void xdg_toplevel_configure(void* data, } } + if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL) { + if(width < 50) width = 50; + if(height < 50) height = 50; + } + MwLLWaylandRegionInvalidate(self); self->wayland.ww = width; self->wayland.wh = height; + // if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL) { + // if(!self->wayland.has_decorations && self->wayland.toplevel->maxim_state) { + // self->wayland.ww -= CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT; + // self->wayland.wh -= CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM; + // } + // } if(self->wayland.resizing == 0) { xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); @@ -226,12 +241,14 @@ static void xdg_surface_configure( } 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); - wl_surface_commit(buffer->surface); + 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); + } } } @@ -245,11 +262,13 @@ static void setup_toplevel(MwLL r, int x, int y) { MwLLWaylandSetupCallbacks(&r->wayland); /* Connect to the Wayland compositor */ - r->wayland.display = wl_display_connect(NULL); - if(r->wayland.display == NULL) { - printf("wayland: failed to create display\n"); - raise(SIGTRAP); - return; + if(!r->wayland.display) { + r->wayland.display = wl_display_connect(NULL); + if(r->wayland.display == NULL) { + printf("wayland: failed to create display\n"); + raise(SIGTRAP); + return; + } } /* Do a roundtrip to ensure all interfaces are setup. */ @@ -264,6 +283,8 @@ 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) { r->wayland.has_decorations = MwTRUE; + } else { + r->wayland.do_csd = MwTRUE; } r->wayland.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); @@ -294,8 +315,13 @@ static void setup_toplevel(MwLL r, int x, int y) { /* Perform the initial commit and wait for the first configure event */ wl_surface_commit(r->wayland.backbuffer.surface); wl_surface_commit(r->wayland.framebuffer.surface); + while(!r->wayland.configured) { - event_loop(r); + if(wl_display_roundtrip(r->wayland.display) == -1) { + printf("roundtrip failed\n"); + raise(SIGTRAP); + return; + } } /* setup decorations if we can */ @@ -308,24 +334,29 @@ static void setup_toplevel(MwLL r, int x, int y) { zxdg_toplevel_decoration_v1_set_mode( dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); } else { - wl_subsurface_set_position(r->wayland.toplevel->ssurface, CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_TOP); + wl_subsurface_set_position(r->wayland.toplevel->ssurface, r->wayland.do_csd ? CSD_BORDER_FRAME_LEFT : 0, r->wayland.do_csd ? CSD_BORDER_FRAME_TOP : 0); } + + MwLLWaylandFramebufferSetup(&r->wayland); + MwLLWaylandBackbufferSetup(&r->wayland); } /* Toplevel destroy function */ static void destroy_toplevel(MwLL r) { if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; + zxdg_toplevel_decoration_v1_destroy(dec->decoration); zxdg_decoration_manager_v1_destroy(dec->manager); } - wl_surface_destroy(r->wayland.framebuffer.surface); + MwLLWaylandFramebufferDestroy(&r->wayland); + MwLLWaylandBackbufferDestroy(&r->wayland); - wl_compositor_destroy(r->wayland.compositor); + xdg_toplevel_destroy(r->wayland.toplevel->xdg_top_level); xdg_surface_destroy(r->wayland.toplevel->xdg_surface); - xdg_toplevel_destroy(r->wayland.toplevel->xdg_top_level); + wl_compositor_destroy(r->wayland.compositor); xkb_keymap_unref(r->wayland.xkb_keymap); @@ -333,12 +364,25 @@ 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); + + 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); - wl_registry_destroy(r->wayland.registry); - - wl_display_disconnect(r->wayland.display); - r->wayland.configured = MwFALSE; } @@ -387,6 +431,9 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.xkb_state = parent->wayland.xkb_state; r->wayland.configured = MwTRUE; + + MwLLWaylandFramebufferSetup(&r->wayland); + MwLLWaylandBackbufferSetup(&r->wayland); } /* Sublevel setup function */ @@ -410,6 +457,8 @@ static void popup_configure(void* data, MwLL self = data; (void)xdg_popup; + if(width < 50) width = 50; + if(height < 50) height = 50; self->wayland.x = x; self->wayland.y = y; self->wayland.ww = width; @@ -426,6 +475,7 @@ static void popup_repositioned(void* data, struct xdg_popup* xdg_popup, uint32_t token) { MwLL self = data; + (void)xdg_popup; xdg_surface_ack_configure(self->wayland.popup->xdg_surface, token); }; @@ -439,20 +489,24 @@ struct xdg_popup_listener popup_listener = { /* Popup setup function */ static void setup_popup(MwLL r, int x, int y, MwLL parent) { - struct xdg_surface* xdg_surface; - MwLL topmost_parent = r->wayland.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)); - 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; + while(topmost_parent->wayland.parent) { + topmost_parent = topmost_parent->wayland.parent; + } - while(topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) { - topmost_parent = topmost_parent->wayland.parent; - } - if(!topmost_parent->wayland.has_decorations) { - r->wayland.x += ceil((float)CSD_BORDER_FRAME_LEFT / 2.); - r->wayland.y += ceil((float)CSD_BORDER_FRAME_TOP / 2.); + if(!topmost_parent->wayland.has_decorations && topmost_parent->wayland.do_csd) { + if(p->is_menu) { + r->wayland.x += round((float)CSD_BORDER_FRAME_LEFT / 2.); + r->wayland.y += ceil((float)CSD_BORDER_FRAME_TOP / 2.); + } + } } MwLLWaylandSetupCallbacks(&r->wayland); @@ -472,6 +526,8 @@ 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) { r->wayland.has_decorations = MwTRUE; + } else { + r->wayland.do_csd = MwTRUE; } r->wayland.popup->xdg_wm_base = WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context; @@ -481,9 +537,14 @@ 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); + 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); - xdg_surface = topmost_parent->wayland.toplevel->xdg_surface; r->wayland.xkb_keymap = topmost_parent->wayland.xkb_keymap; r->wayland.xkb_state = topmost_parent->wayland.xkb_state; @@ -492,40 +553,217 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { r->wayland.popup->xdg_surface = xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface); - r->wayland.popup->xdg_popup = xdg_surface_get_popup( - r->wayland.popup->xdg_surface, - xdg_surface, - r->wayland.popup->xdg_positioner); - - uint32_t ver = wl_proxy_get_version((struct wl_proxy*)r->wayland.popup->xdg_popup); + if(topmost_parent->wayland.type == MwLL_WAYLAND_TOPLEVEL) { + r->wayland.popup->xdg_popup = xdg_surface_get_popup( + r->wayland.popup->xdg_surface, + topmost_parent->wayland.toplevel->xdg_surface, + r->wayland.popup->xdg_positioner); + } else if(topmost_parent->wayland.type == MwLL_WAYLAND_LAYER_SURFACE) { + r->wayland.popup->xdg_popup = xdg_surface_get_popup( + r->wayland.popup->xdg_surface, NULL, + r->wayland.popup->xdg_positioner); + zwlr_layer_surface_v1_get_popup(topmost_parent->wayland.layer_surface->surface, r->wayland.popup->xdg_popup); + } xdg_popup_add_listener(r->wayland.popup->xdg_popup, &popup_listener, r); r->wayland.popup->xdg_surface_listener.configure = xdg_surface_configure; xdg_surface_add_listener(r->wayland.popup->xdg_surface, &r->wayland.popup->xdg_surface_listener, r); - /* Perform the initial commit and wait for the first configure event */ - wl_surface_commit(r->wayland.framebuffer.surface); - while(!r->wayland.configured) { - event_loop(r); + if(wl_display_roundtrip(r->wayland.display) == -1) { + printf("roundtrip failed\n"); + raise(SIGTRAP); + return; } + + MwLLWaylandFramebufferSetup(&r->wayland); } /* Popup destroy function */ static void destroy_popup(MwLL r) { - xdg_popup_destroy(r->wayland.popup->xdg_popup); + + MwLLWaylandBackbufferDestroy(&r->wayland); + MwLLWaylandFramebufferDestroy(&r->wayland); xdg_surface_destroy(r->wayland.popup->xdg_surface); + xdg_popup_destroy(r->wayland.popup->xdg_popup); + xdg_positioner_destroy(r->wayland.popup->xdg_positioner); wl_surface_destroy(r->wayland.framebuffer.surface); wl_registry_destroy(r->wayland.registry); + free(r->wayland.popup); + r->wayland.configured = MwFALSE; } +static void layer_shell_configure(void* data, + struct zwlr_layer_surface_v1* surface, + uint32_t serial, + uint32_t width, + uint32_t height) { + MwLL self = data; + zwlr_layer_surface_v1_ack_configure(surface, serial); + + if(width < 50) width = 50; + if(height < 50) height = 50; + + self->wayland.ww = width; + self->wayland.wh = height; + + self->wayland.configured = MwTRUE; + + MwLLWaylandFramebufferSetup(&self->wayland); + MwLLWaylandRegionSetup(self); + MwLLDispatch(self, resize, NULL); + + wl_surface_commit(self->wayland.framebuffer.surface); +}; + +static void layer_shell_done(void* data, + struct zwlr_layer_surface_v1* zwlr_layer_surface_v1) { + (void)data; + (void)zwlr_layer_surface_v1; + + printf("closed\n"); +}; + +static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_shell_configure, + .closed = layer_shell_done, +}; + +/* Layer surface setup function */ +static void setup_layer_surface(MwLL r, int x, int y, int width, int height) { + wayland_protocol_t* layer_shell_protocol; + struct zwlr_layer_shell_v1* layer_shell; + r->wayland.type = MwLL_WAYLAND_LAYER_SURFACE; + r->wayland.layer_surface = malloc(sizeof(struct _MwLLWaylandLayerSurface)); + r->wayland.x = x; + r->wayland.y = y; + + MwLLWaylandSetupCallbacks(&r->wayland); + + /* Connect to the Wayland compositor */ + if(!r->wayland.display) { + r->wayland.display = wl_display_connect(NULL); + if(r->wayland.display == NULL) { + printf("wayland: failed to create display\n"); + raise(SIGTRAP); + return; + } + } + + /* Do a roundtrip to ensure all interfaces are setup. */ + r->wayland.registry = wl_display_get_registry(r->wayland.display); + wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); + if(wl_display_roundtrip(r->wayland.display) == -1) { + printf("roundtrip failed\n"); + raise(SIGTRAP); + return; + } + + layer_shell_protocol = WAYLAND_GET_INTERFACE(r->wayland, zwlr_layer_shell_v1); + assert(layer_shell_protocol); + + layer_shell = layer_shell_protocol->context; + + r->wayland.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); + + 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"); + + zwlr_layer_surface_v1_set_size(r->wayland.layer_surface->surface, width, height); + zwlr_layer_surface_v1_set_margin(r->wayland.layer_surface->surface, + y, 0, 0, x); + zwlr_layer_surface_v1_set_anchor(r->wayland.layer_surface->surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); + zwlr_layer_surface_v1_set_exclusive_zone(r->wayland.layer_surface->surface, 1); + zwlr_layer_surface_v1_set_keyboard_interactivity( + r->wayland.layer_surface->surface, ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND); + + zwlr_layer_surface_v1_add_listener(r->wayland.layer_surface->surface, &layer_surface_listener, r); + + /* Perform the initial commit and wait for the first configure event */ + wl_surface_commit(r->wayland.framebuffer.surface); + + if(wl_display_roundtrip(r->wayland.display) == -1) { + printf("roundtrip failed\n"); + raise(SIGTRAP); + return; + } +} + +/* Toplevel destroy function */ +static void destroy_layer_surface(MwLL r) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; + zxdg_decoration_manager_v1_destroy(dec->manager); + } + + wl_surface_destroy(r->wayland.framebuffer.surface); + + wl_compositor_destroy(r->wayland.compositor); + + xkb_keymap_unref(r->wayland.xkb_keymap); + + xkb_state_unref(r->wayland.xkb_state); + + xkb_context_unref(r->wayland.xkb_context); + + wl_registry_destroy(r->wayland.registry); + + r->wayland.configured = MwFALSE; +} + +static void destroy_widget(MwLL handle) { + int i; + + MwLLShow(handle, MwFALSE); + + switch(handle->wayland.type) { + case MwLL_WAYLAND_TOPLEVEL: + destroy_toplevel(handle); + break; + case MwLL_WAYLAND_SUBLEVEL: + destroy_sublevel(handle); + break; + case MwLL_WAYLAND_POPUP: + destroy_popup(handle); + break; + case MwLL_WAYLAND_LAYER_SURFACE: + destroy_layer_surface(handle); + break; + default: + printf("Handle with unknown type(%d) tried to be destroyed (%p)\n", handle->wayland.type, handle); + break; + } + + if(wl_display_roundtrip(handle->wayland.display) == -1) { + printf("roundtrip failed\n"); + raise(SIGTRAP); + return; + } + + for(i = 0; i < shlen(handle->wayland.wl_protocol_setup_map); i++) { + void* ctx = shget(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].key); + + if(ctx != NULL) { + handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx); + } + shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value); + free(handle->wayland.wl_protocol_setup_map[i].value); + } + + shfree(handle->wayland.wl_protocol_map); + shfree(handle->wayland.wl_protocol_setup_map); + + MwLLWaylandFlush(handle); +} + static void clip(MwLL handle) { int i; int x, y, cx, cy, mx, my; @@ -541,6 +779,7 @@ static void clip(MwLL handle) { toplevel = toplevel->wayland.parent; } if(toplevel) { + #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) /* i seriously have no fucking idea how this works, do not ask me how this really works (nishi) */ @@ -588,15 +827,15 @@ static void clip(MwLL handle) { handle->wayland.clipping_rect.height = my - cy; MwLLWaylandRegionSetup(handle); - cairo_reset_clip(handle->wayland.front_cairo); + cairo_reset_clip(handle->wayland.cairo.front_cairo); if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL && !handle->wayland.is_toplevel) { - cairo_rectangle(handle->wayland.front_cairo, cx - x, cy - y, mx - cx, my - cy); - cairo_clip(handle->wayland.front_cairo); + cairo_rectangle(handle->wayland.cairo.front_cairo, cx - x, cy - y, mx - cx, my - cy); + cairo_clip(handle->wayland.cairo.front_cairo); } if(handle->wayland.is_clipping) { - cairo_rectangle(handle->wayland.front_cairo, handle->wayland.clip.x, handle->wayland.clip.y, handle->wayland.clip.width, handle->wayland.clip.height); - cairo_clip(handle->wayland.front_cairo); + 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); } } } @@ -652,16 +891,26 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh setup_sublevel(parent, r, x, y); break; case MwLL_WAYLAND_POPUP: - setup_popup(r, x, y, parent); + if(parent) { + setup_popup(r, x, y, parent); + } else { + /* + * We can't actually have a popup without a parent but this needs to be valid behavior. + * If we're down this code path, though, it means we can't create a layer surface. + * So we just fake it with a borderless window. + */ + setup_toplevel(r, x, y); + MwLLMakeBorderless(r, MwTRUE); + } + break; + case MwLL_WAYLAND_LAYER_SURFACE: + setup_layer_surface(r, x, y, width, height); break; } } WIDGET_CHECK(r); - MwLLWaylandFramebufferSetup(&r->wayland); - MwLLWaylandBackbufferSetup(&r->wayland); - r->wayland.region = wl_compositor_create_region(r->wayland.compositor); r->wayland.o_region = wl_compositor_create_region(r->wayland.compositor); MwLLWaylandRegionSetup(r); @@ -671,7 +920,11 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh MwLLForceRender(parent); } - if(!r->wayland.has_decorations) { + /* If the compositor never sets the keyboard repeat info, we'll copy KDE's default of... */ + r->wayland.keyboard_delay = 600; /* starting at 600ms... */ + r->wayland.keyboard_rate = 25; /* and going every 25ms... */ + + if(!r->wayland.has_decorations && r->wayland.do_csd) { MwLLBeginDraw(r); MwLLEndDraw(r); } @@ -764,28 +1017,11 @@ static void MwLLDestroyImpl(MwLL handle) { wl_surface_destroy(handle->wayland.icon->surface); } - if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { - destroy_toplevel(handle); - } else if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - destroy_sublevel(handle); - } else if(handle->wayland.type == MwLL_WAYLAND_POPUP) { - destroy_popup(handle); - } + destroy_widget(handle); + } else { + printf("widget invalid\n"); } - for(i = 0; i < shlen(handle->wayland.wl_protocol_setup_map); i++) { - void* ctx = shget(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].key); - - if(ctx != NULL) { - handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx); - } - shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value); - } - shfree(handle->wayland.wl_protocol_map); - shfree(handle->wayland.wl_protocol_setup_map); - - MwLLWaylandFlush(handle); - pthread_mutex_lock(&destroyedWidgetsTableMutex); arrput(destroyedWidgetsTable, handle); pthread_mutex_unlock(&destroyedWidgetsTableMutex); @@ -816,15 +1052,26 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { MwLLWaylandRegionInvalidate(handle); handle->wayland.x = x; handle->wayland.y = y; - if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - wl_subsurface_set_position(handle->wayland.sublevel->subsurface, x, y); - } - if(handle->wayland.type == MwLL_WAYLAND_POPUP) { + switch(handle->wayland.type) { + case MwLL_WAYLAND_TOPLEVEL: + /* toplevels cannot be moved */ + break; + case MwLL_WAYLAND_SUBLEVEL: + wl_subsurface_set_position(handle->wayland.sublevel->subsurface, 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); xdg_positioner_set_offset(handle->wayland.popup->xdg_positioner, x, y); xdg_popup_reposition(handle->wayland.popup->xdg_popup, handle->wayland.popup->xdg_positioner, 0); xdg_surface_set_window_geometry(handle->wayland.popup->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + break; + case MwLL_WAYLAND_LAYER_SURFACE: + zwlr_layer_surface_v1_set_margin(handle->wayland.layer_surface->surface, + y, 0, 0, x); + break; + case MwLL_WAYLAND_UNKNOWN: + break; } MwLLWaylandRegionSetup(handle); @@ -847,7 +1094,7 @@ static void actually_set_wh(MwLL handle) { } if(handle->wayland.type == MwLL_WAYLAND_POPUP) { - destroy_popup(handle); + destroy_widget(handle); MwLLWaylandFlush(handle); setup_popup(handle, handle->wayland.x, handle->wayland.y, handle->wayland.parent); } @@ -870,14 +1117,14 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { } /* Prevent an integer underflow when the w/h is too low */ - if((w < 2 || h < 2)) { - handle->wayland.ww = 2; - handle->wayland.wh = 2; - } else { - handle->wayland.ww = w; - handle->wayland.wh = h; + if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { + if(w < 50) w = 50; + if(h < 50) h = 50; } + handle->wayland.ww = w; + handle->wayland.wh = h; + if(!handle->wayland.setting_wh) { handle->wayland.setting_wh = 1; } @@ -885,59 +1132,117 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { handle->wayland.events_pending = 1; } +typedef struct { + double r, g, b; +} float_color; +static float_color lerp_color(float_color a, float_color b, float t) { + return (float_color){ + a.r + (b.r - a.r) * t, + a.g + (b.g - a.g) * t, + a.b + (b.b - a.b) * t}; +} +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.front_cairo); - cairo_set_source_rgba(handle->wayland.front_cairo, 0, 0, 0, 0); - cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_SOURCE); - cairo_rectangle(handle->wayland.front_cairo, 0, 0, handle->wayland.ww, handle->wayland.wh); - cairo_fill(handle->wayland.front_cairo); - cairo_restore(handle->wayland.front_cairo); + 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); if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) { - handle->wayland.selected_cairo = handle->wayland.front_cairo; + handle->wayland.cairo.selected_cairo = handle->wayland.cairo.front_cairo; return; } - if(!handle->wayland.has_decorations) { - int x; - MwU32 w = handle->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT; - MwU32 h = handle->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM; - cairo_set_line_width(handle->wayland.back_cairo, 4.0); - for(x = 0; x < w; x++) { - float placeholder = (float)x / (float)w; - cairo_set_source_rgb(handle->wayland.back_cairo, placeholder, 0.25, 0.25); + if(!handle->wayland.has_decorations && handle->wayland.do_csd) { + int y; + MwU32 w = handle->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT; + MwU32 h = handle->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM; + MwRect r; + handle->wayland.cairo.selected_cairo = handle->wayland.cairo.back_cairo; - cairo_move_to(handle->wayland.back_cairo, w - x, 0); - cairo_line_to(handle->wayland.back_cairo, w - x, CSD_BORDER_FRAME_TOP); - cairo_stroke(handle->wayland.back_cairo); +#define DO_BOX(x, y, col, w, h) \ + cairo_rectangle(handle->wayland.cairo.back_cairo, x, y, w, h); \ + cairo_set_source_rgb(handle->wayland.cairo.back_cairo, col, col, col); \ + cairo_fill(handle->wayland.cairo.back_cairo); - cairo_move_to(handle->wayland.back_cairo, x, CSD_BORDER_FRAME_TOP); - cairo_line_to(handle->wayland.back_cairo, x, h); - cairo_stroke(handle->wayland.back_cairo); +#define DO_LINE(off, col) \ + cairo_move_to(handle->wayland.cairo.back_cairo, off, off); \ + cairo_line_to(handle->wayland.cairo.back_cairo, off, h - (off)); \ + cairo_set_source_rgb(handle->wayland.cairo.back_cairo, col, col, col); \ + cairo_stroke(handle->wayland.cairo.back_cairo); \ + cairo_move_to(handle->wayland.cairo.back_cairo, off, off); \ + cairo_line_to(handle->wayland.cairo.back_cairo, w - (off), off); \ + cairo_set_source_rgb(handle->wayland.cairo.back_cairo, col, col, col); \ + cairo_stroke(handle->wayland.cairo.back_cairo); + + /* border */ + cairo_set_antialias(handle->wayland.cairo.back_cairo, CAIRO_ANTIALIAS_NONE); + + DO_BOX(0, 0, 0.14901961, w, h); + DO_BOX(1, 1, 0.55686275, w - 2, h - 2); + DO_BOX(2, 2, 0.82352941, w - 4, h - 4); + DO_BOX(3, 3, 0.93333333, w - 6, h - 6); + DO_BOX(4, 4, 1, w - 8, h - 8); + DO_BOX(4, 4, 0.14901961, w - CSD_BORDER_FRAME_LEFT - 4, h - CSD_BORDER_FRAME_BOTTOM - 4); + cairo_set_line_width(handle->wayland.cairo.back_cairo, 1.0); + + DO_LINE(1, 1) + DO_LINE(2, 0.93333333) + DO_LINE(3, 0.82352941) + DO_LINE(4, 0.55686275) + DO_LINE(5, 0.14901961) + + cairo_set_line_width(handle->wayland.cairo.back_cairo, 2.0); + for(y = 1; y < CSD_BORDER_FRAME_TOP - CSD_BORDER_FRAME_LEFT; y++) { + float_color c = lerp_color(one, two, (double)y / (double)(CSD_BORDER_FRAME_TOP - CSD_BORDER_FRAME_LEFT)); + + cairo_set_source_rgb(handle->wayland.cairo.back_cairo, c.r, c.g, c.b); + + cairo_move_to(handle->wayland.cairo.back_cairo, CSD_BORDER_FRAME_LEFT, y + CSD_BORDER_FRAME_LEFT); + cairo_line_to(handle->wayland.cairo.back_cairo, w - CSD_BORDER_FRAME_RIGHT, y + CSD_BORDER_FRAME_LEFT); + cairo_stroke(handle->wayland.cairo.back_cairo); } - cairo_set_source_rgba(handle->wayland.back_cairo, 1, 1, 1, 0.5); - cairo_move_to(handle->wayland.back_cairo, 0, 0); - cairo_line_to(handle->wayland.back_cairo, 0, h); - cairo_stroke(handle->wayland.back_cairo); - cairo_move_to(handle->wayland.back_cairo, 0, 0); - cairo_line_to(handle->wayland.back_cairo, w, 0); - cairo_stroke(handle->wayland.back_cairo); - cairo_set_source_rgba(handle->wayland.back_cairo, 0, 0, 0, 0.5); - cairo_move_to(handle->wayland.back_cairo, 0, h); - cairo_line_to(handle->wayland.back_cairo, w, h); - cairo_stroke(handle->wayland.back_cairo); - cairo_move_to(handle->wayland.back_cairo, w, 0); - cairo_line_to(handle->wayland.back_cairo, w, h); - cairo_stroke(handle->wayland.back_cairo); + /* icon */ + r.x = CSD_BORDER_FRAME_LEFT + 1; + r.y = CSD_BORDER_FRAME_RIGHT + 1; + r.width = 15; + r.height = 15; + DO_BOX(5, 5, 1, 18, 18); + DO_BOX(6, 6, 0.35294118, 17, 17); + DO_BOX(6, 6, 0.82352941, 16, 16); + handle->wayland.cairo.selected_cairo = handle->wayland.cairo.back_cairo; + if(handle->wayland.icon_pixmap) { + MwLLDrawPixmap(handle, &r, handle->wayland.icon_pixmap); + } + /* close */ + DO_BOX(w - 19 - CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_BOTTOM + 1, 1, 18, 18); + DO_BOX(w - 18 - CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_BOTTOM + 2, 0.35294118, 17, 17); + DO_BOX(w - 18 - CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_BOTTOM + 2, 0.82352941, 16, 16); + DO_BOX(w - 18 - CSD_BORDER_FRAME_LEFT + 5, CSD_BORDER_FRAME_BOTTOM + 7, 0, 6, 6); + DO_BOX(w - 18 - CSD_BORDER_FRAME_LEFT + 6, CSD_BORDER_FRAME_BOTTOM + 8, 0.82352941, 4, 4); + + /* maxim */ + DO_BOX(w - 37 - CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_BOTTOM + 1, 1, 18, 18); + DO_BOX(w - 36 - CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_BOTTOM + 2, 0.35294118, 17, 17); + DO_BOX(w - 36 - CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_BOTTOM + 2, 0.82352941, 16, 16); + DO_BOX(w - 36 - CSD_BORDER_FRAME_LEFT + 5, CSD_BORDER_FRAME_BOTTOM + 7, 0, 6, 6); + DO_BOX(w - 36 - CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_BOTTOM + 9, 0.82352941, 16, 2); + DO_BOX(w - 36 - CSD_BORDER_FRAME_LEFT + 7, CSD_BORDER_FRAME_BOTTOM + 4, 0.82352941, 2, 14); + DO_BOX(w - 36 - CSD_BORDER_FRAME_LEFT + 6, CSD_BORDER_FRAME_BOTTOM + 8, 0.82352941, 4, 4); + + /* title */ if(strlen(handle->wayland.title) != 0) { int y, x; int i = 0, sx = 0, sy = 0; int tw, th; unsigned char* px; - MwRect r; MwLLPixmap p; tw = strlen(handle->wayland.title) * 7; th = 14; @@ -946,8 +1251,6 @@ static void MwLLBeginDrawImpl(MwLL handle) { memset(px, 0, tw * th * 4); - handle->wayland.selected_cairo = handle->wayland.back_cairo; - while(handle->wayland.title[i]) { int out; i += MwUTF8ToUTF32(handle->wayland.title + i, &out); @@ -970,8 +1273,8 @@ static void MwLLBeginDrawImpl(MwLL handle) { } p = MwLLCreatePixmap(handle, px, tw, th); - r.x = 5; - r.y = 5; + r.x = 24; + r.y = 5 + 2; r.width = tw; r.height = th; @@ -981,7 +1284,7 @@ static void MwLLBeginDrawImpl(MwLL handle) { } MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } - handle->wayland.selected_cairo = handle->wayland.front_cairo; + handle->wayland.cairo.selected_cairo = handle->wayland.cairo.front_cairo; } static void MwLLEndDrawImpl(MwLL handle) { @@ -994,25 +1297,11 @@ static void MwLLEndDrawImpl(MwLL handle) { } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - int i; WIDGET_CHECK(handle); clip(handle); - cairo_set_source_rgba(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); - cairo_new_path(handle->wayland.front_cairo); - for(i = 0; i < points_count; i++) { - if(i == 0) { - cairo_move_to(handle->wayland.front_cairo, points[i].x, points[i].y); - } else { - cairo_line_to(handle->wayland.front_cairo, points[i].x, points[i].y); - } - } - cairo_close_path(handle->wayland.front_cairo); - - cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_SOURCE); - cairo_fill(handle->wayland.front_cairo); - cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_OVER); + MwLLCairoPolygon(handle->wayland.cairo, points, points_count, color); handle->wayland.events_pending = 1; } @@ -1023,19 +1312,7 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { clip(handle); - cairo_set_antialias(handle->wayland.front_cairo, CAIRO_ANTIALIAS_NONE); - cairo_set_line_cap(handle->wayland.front_cairo, CAIRO_LINE_CAP_SQUARE); - cairo_set_source_rgba(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); - cairo_new_path(handle->wayland.front_cairo); - for(i = 0; i < 2; i++) { - if(i == 0) { - cairo_move_to(handle->wayland.front_cairo, points[i].x, points[i].y); - } else { - cairo_line_to(handle->wayland.front_cairo, points[i].x, points[i].y); - } - } - cairo_close_path(handle->wayland.front_cairo); - cairo_stroke(handle->wayland.front_cairo); + MwLLCairoLine(handle->wayland.cairo, points, color); handle->wayland.events_pending = 1; } @@ -1084,6 +1361,20 @@ static int MwLLPendingImpl(MwLL handle) { handle->wayland.setting_wh = 0; } + handle->wayland.end_time = MwTimeGetTick(); + + 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; + } + handle->wayland.next_elapsed = elapsed + handle->wayland.keyboard_rate; + } + } + #ifdef USE_DBUS if(wl_call_tbl.has_dbus) { if(handle->wayland.dark_theme_detection) { @@ -1152,88 +1443,33 @@ 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); } - if(!handle->wayland.has_decorations) { + if(!handle->wayland.has_decorations && handle->wayland.do_csd) { strncpy(handle->wayland.title, title, 255); MwLLBeginDraw(handle); MwLLEndDraw(handle); + + xdg_toplevel_set_min_size(handle->wayland.toplevel->xdg_top_level, (strlen(handle->wayland.title) * 8) + 64, 64); } } static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { - MwLLPixmap r = malloc(sizeof(*r)); - (void)handle; - - if(width >= INT16_MAX) width = INT16_MAX; - if(height >= INT16_MAX) height = INT16_MAX; - - r->common.width = width; - r->common.height = height; - r->common.raw = malloc(4 * width * height); - memcpy(r->common.raw, data, 4 * width * height); - - r->wayland.cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - - MwLLPixmapUpdate(r); - - return r; + return MwLLCairoCreatePixmap(handle->wayland.cairo, data, width, height); } static void MwLLPixmapUpdateImpl(MwLLPixmap r) { - int i; - unsigned char* d; - - cairo_surface_flush(r->wayland.cs); - d = cairo_image_surface_get_data(r->wayland.cs); - for(i = 0; i < r->common.width * r->common.height * 4; i += 4) { - MwU32* p = (MwU32*)&d[i]; - *p <<= 8; - *p |= r->common.raw[i + 3]; - *p <<= 8; - *p |= r->common.raw[i + 0]; - *p <<= 8; - *p |= r->common.raw[i + 1]; - *p <<= 8; - *p |= r->common.raw[i + 2]; - } - cairo_surface_mark_dirty(r->wayland.cs); + MwLLCairoPixmapUpdate(r); } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { - cairo_surface_destroy(pixmap->wayland.cs); - free(pixmap->common.raw); - free(pixmap); + MwLLCairoDestroyPixmap(pixmap); } static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - cairo_t* c; - cairo_surface_t* cs; - cairo_t* selected_cairo = handle->wayland.selected_cairo ? handle->wayland.selected_cairo : handle->wayland.front_cairo; - - if(rect->width <= 0 || rect->height <= 0 || pixmap->common.width <= 0 || pixmap->common.height <= 0) return; - if(rect->width >= INT16_MAX) rect->width = INT16_MAX; - if(rect->height >= INT16_MAX) rect->height = INT16_MAX; - WIDGET_CHECK(handle); - cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); - c = cairo_create(cs); - clip(handle); - cairo_scale(c, (double)rect->width / pixmap->common.width, (double)rect->height / pixmap->common.height); - - cairo_set_source_surface(c, pixmap->wayland.cs, 0, 0); - cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); - - cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_OVER); - - cairo_paint(c); - - cairo_set_source_surface(selected_cairo, cs, rect->x, rect->y); - cairo_paint(selected_cairo); - - cairo_destroy(c); - cairo_surface_destroy(cs); + MwLLCairoDrawPixmap(handle->wayland.cairo, rect, pixmap); MwLLForceRender(handle); wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); @@ -1279,6 +1515,17 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { xdg_toplevel_icon_manager_v1_set_icon(icon_manager, handle->wayland.toplevel->xdg_top_level, icon); } } + if(!handle->wayland.has_decorations && handle->wayland.do_csd) { + if(handle->wayland.icon_pixmap) { + MwLLDestroyPixmap(handle->wayland.icon_pixmap); + } + handle->wayland.icon_pixmap = MwLLCreatePixmap(handle, pixmap->common.raw, pixmap->common.width, pixmap->common.height); + + actually_set_wh(handle); + actually_set_wh(handle); + MwLLBeginDraw(handle); + MwLLEndDraw(handle); + } } static void MwLLForceRenderImpl(MwLL handle) { @@ -1348,11 +1595,16 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { int x = 0, y = 0; WIDGET_CHECK(handle); while(p != NULL) { - x += p->wayland.x; - y += p->wayland.y; + if(p->wayland.type != MwLL_WAYLAND_TOPLEVEL) { + x += p->wayland.x; + y += p->wayland.y; + } else { + break; + } p = p->wayland.parent; } + handle->wayland.changing = MwTRUE; handle->wayland.detatching = MwTRUE; handle->wayland.detach_point = *point; handle->wayland.detach_point.x += x; @@ -1386,21 +1638,29 @@ static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int 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); + + wl_surface_commit(handle->wayland.framebuffer.surface); + wl_surface_commit(handle->wayland.backbuffer.surface); } } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { - (void)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; - dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( - dec->manager, handle->wayland.toplevel->xdg_top_level); + if(!dec->decoration) { + dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( + dec->manager, handle->wayland.toplevel->xdg_top_level); + } + zxdg_toplevel_decoration_v1_unset_mode(dec->decoration); zxdg_toplevel_decoration_v1_set_mode( - dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); + 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); } } } @@ -1486,9 +1746,19 @@ static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) { } static void MwLLMakeToolWindowImpl(MwLL handle) { + MwBool can_do_layer_surface = MwFALSE; + WIDGET_CHECK(handle); - handle->wayland.type_to_be = MwLL_WAYLAND_POPUP; + can_do_layer_surface = (WAYLAND_GET_INTERFACE(handle->wayland, zwlr_layer_shell_v1) != NULL); + + if(!handle->wayland.parent && can_do_layer_surface) { + handle->wayland.type_to_be = MwLL_WAYLAND_LAYER_SURFACE; + } else { + handle->wayland.type_to_be = MwLL_WAYLAND_POPUP; + } + + handle->wayland.changing = MwTRUE; } static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { @@ -1509,76 +1779,93 @@ 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 */ } static void MwLLEndStateChangeImpl(MwLL handle) { + MwLL topmost_parent; + int x, y; WIDGET_CHECK(handle); - if(handle->wayland.detatching) { - MwLL topmost_parent = handle->wayland.parent; + if(!handle->wayland.changing) { + return; + } + handle->wayland.changing = MwFALSE; - while(topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) { + x = handle->wayland.detatching ? handle->wayland.detach_point.x : handle->wayland.x; + y = handle->wayland.detatching ? handle->wayland.detach_point.y : handle->wayland.y; + + topmost_parent = handle->wayland.parent; + + while(topmost_parent) { + if(topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) { topmost_parent = topmost_parent->wayland.parent; - } - switch(handle->wayland.type) { - case MwLL_WAYLAND_UNKNOWN: - break; - case MwLL_WAYLAND_TOPLEVEL: - destroy_toplevel(handle); - break; - case MwLL_WAYLAND_SUBLEVEL: - destroy_sublevel(handle); - break; - case MwLL_WAYLAND_POPUP: - destroy_popup(handle); + } else { break; } + } - MwLLWaylandFlush(handle); + destroy_widget(handle); - widget_setup(handle, handle->wayland.parent, handle->wayland.detach_point.x, handle->wayland.detach_point.y, handle->wayland.ww, handle->wayland.wh, handle->wayland.type_to_be); + if(wl_display_roundtrip(handle->wayland.display) == -1) { + printf("roundtrip failed\n"); + raise(SIGTRAP); + return; + } - handle->wayland.is_toplevel = MwTRUE; + MwLLWaylandFlush(handle); - if(!handle->wayland.parent) - handle->wayland.dark_theme_detection = MwTRUE; + widget_setup(handle, handle->wayland.parent, x, y, handle->wayland.ww, handle->wayland.wh, handle->wayland.type_to_be); - 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; + handle->wayland.is_toplevel = MwTRUE; + + 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); + 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); - MwLLEndStateChangeImpl(w->children[i]->lowlevel); + 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; } } } - - recursive_render(handle); - - handle->wayland.events_pending = 1; - - handle->wayland.detatching = MwFALSE; } + + recursive_render(handle); + + handle->wayland.events_pending = 1; + + handle->wayland.detatching = MwFALSE; } static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { - (void)handle; (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); + MwLLDispatch(handle, draw, NULL); } static MwBool MwLLDoModernImpl(MwLL handle) { 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/color.c b/src/color.c index 49c06d6..ae3667e 100644 --- a/src/color.c +++ b/src/color.c @@ -1,5 +1,14 @@ #include +#include "../external/stb_ds.h" + +struct color { + char* key; + MwU32 value; +}; + +static struct color* colors = NULL; + MwLLColor MwParseColorName(MwWidget handle, const char* color) { MwRGB rgb; MwParseColorNameNoAllocate(color, &rgb); @@ -7,4699 +16,800 @@ MwLLColor MwParseColorName(MwWidget handle, const char* color) { } void MwParseColorNameNoAllocate(const char* color, MwRGB* rgb) { - if(strcmp(color, "snow") == 0) { - rgb->red = 255; - rgb->green = 250; - rgb->blue = 250; - return; - } - if(strcmp(color, "ghost white") == 0) { - rgb->red = 248; - rgb->green = 248; - rgb->blue = 255; - return; - } - if(strcmp(color, "GhostWhite") == 0) { - rgb->red = 248; - rgb->green = 248; - rgb->blue = 255; - return; - } - if(strcmp(color, "white smoke") == 0) { - rgb->red = 245; - rgb->green = 245; - rgb->blue = 245; - return; - } - if(strcmp(color, "WhiteSmoke") == 0) { - rgb->red = 245; - rgb->green = 245; - rgb->blue = 245; - return; - } - if(strcmp(color, "gainsboro") == 0) { - rgb->red = 220; - rgb->green = 220; - rgb->blue = 220; - return; - } - if(strcmp(color, "floral white") == 0) { - rgb->red = 255; - rgb->green = 250; - rgb->blue = 240; - return; - } - if(strcmp(color, "FloralWhite") == 0) { - rgb->red = 255; - rgb->green = 250; - rgb->blue = 240; - return; - } - if(strcmp(color, "old lace") == 0) { - rgb->red = 253; - rgb->green = 245; - rgb->blue = 230; - return; - } - if(strcmp(color, "OldLace") == 0) { - rgb->red = 253; - rgb->green = 245; - rgb->blue = 230; - return; - } - if(strcmp(color, "linen") == 0) { - rgb->red = 250; - rgb->green = 240; - rgb->blue = 230; - return; - } - if(strcmp(color, "antique white") == 0) { - rgb->red = 250; - rgb->green = 235; - rgb->blue = 215; - return; - } - if(strcmp(color, "AntiqueWhite") == 0) { - rgb->red = 250; - rgb->green = 235; - rgb->blue = 215; - return; - } - if(strcmp(color, "papaya whip") == 0) { - rgb->red = 255; - rgb->green = 239; - rgb->blue = 213; - return; - } - if(strcmp(color, "PapayaWhip") == 0) { - rgb->red = 255; - rgb->green = 239; - rgb->blue = 213; - return; - } - if(strcmp(color, "blanched almond") == 0) { - rgb->red = 255; - rgb->green = 235; - rgb->blue = 205; - return; - } - if(strcmp(color, "BlanchedAlmond") == 0) { - rgb->red = 255; - rgb->green = 235; - rgb->blue = 205; - return; - } - if(strcmp(color, "bisque") == 0) { - rgb->red = 255; - rgb->green = 228; - rgb->blue = 196; - return; - } - if(strcmp(color, "peach puff") == 0) { - rgb->red = 255; - rgb->green = 218; - rgb->blue = 185; - return; - } - if(strcmp(color, "PeachPuff") == 0) { - rgb->red = 255; - rgb->green = 218; - rgb->blue = 185; - return; - } - if(strcmp(color, "navajo white") == 0) { - rgb->red = 255; - rgb->green = 222; - rgb->blue = 173; - return; - } - if(strcmp(color, "NavajoWhite") == 0) { - rgb->red = 255; - rgb->green = 222; - rgb->blue = 173; - return; - } - if(strcmp(color, "moccasin") == 0) { - rgb->red = 255; - rgb->green = 228; - rgb->blue = 181; - return; - } - if(strcmp(color, "cornsilk") == 0) { - rgb->red = 255; - rgb->green = 248; - rgb->blue = 220; - return; - } - if(strcmp(color, "ivory") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 240; - return; - } - if(strcmp(color, "lemon chiffon") == 0) { - rgb->red = 255; - rgb->green = 250; - rgb->blue = 205; - return; - } - if(strcmp(color, "LemonChiffon") == 0) { - rgb->red = 255; - rgb->green = 250; - rgb->blue = 205; - return; - } - if(strcmp(color, "seashell") == 0) { - rgb->red = 255; - rgb->green = 245; - rgb->blue = 238; - return; - } - if(strcmp(color, "honeydew") == 0) { - rgb->red = 240; - rgb->green = 255; - rgb->blue = 240; - return; - } - if(strcmp(color, "mint cream") == 0) { - rgb->red = 245; - rgb->green = 255; - rgb->blue = 250; - return; - } - if(strcmp(color, "MintCream") == 0) { - rgb->red = 245; - rgb->green = 255; - rgb->blue = 250; - return; - } - if(strcmp(color, "azure") == 0) { - rgb->red = 240; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "alice blue") == 0) { - rgb->red = 240; - rgb->green = 248; - rgb->blue = 255; - return; - } - if(strcmp(color, "AliceBlue") == 0) { - rgb->red = 240; - rgb->green = 248; - rgb->blue = 255; - return; - } - if(strcmp(color, "lavender") == 0) { - rgb->red = 230; - rgb->green = 230; - rgb->blue = 250; - return; - } - if(strcmp(color, "lavender blush") == 0) { - rgb->red = 255; - rgb->green = 240; - rgb->blue = 245; - return; - } - if(strcmp(color, "LavenderBlush") == 0) { - rgb->red = 255; - rgb->green = 240; - rgb->blue = 245; - return; - } - if(strcmp(color, "misty rose") == 0) { - rgb->red = 255; - rgb->green = 228; - rgb->blue = 225; - return; - } - if(strcmp(color, "MistyRose") == 0) { - rgb->red = 255; - rgb->green = 228; - rgb->blue = 225; - return; - } - if(strcmp(color, "white") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "black") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "dark slate gray") == 0) { - rgb->red = 47; - rgb->green = 79; - rgb->blue = 79; - return; - } - if(strcmp(color, "DarkSlateGray") == 0) { - rgb->red = 47; - rgb->green = 79; - rgb->blue = 79; - return; - } - if(strcmp(color, "dark slate grey") == 0) { - rgb->red = 47; - rgb->green = 79; - rgb->blue = 79; - return; - } - if(strcmp(color, "DarkSlateGrey") == 0) { - rgb->red = 47; - rgb->green = 79; - rgb->blue = 79; - return; - } - if(strcmp(color, "dim gray") == 0) { - rgb->red = 105; - rgb->green = 105; - rgb->blue = 105; - return; - } - if(strcmp(color, "DimGray") == 0) { - rgb->red = 105; - rgb->green = 105; - rgb->blue = 105; - return; - } - if(strcmp(color, "dim grey") == 0) { - rgb->red = 105; - rgb->green = 105; - rgb->blue = 105; - return; - } - if(strcmp(color, "DimGrey") == 0) { - rgb->red = 105; - rgb->green = 105; - rgb->blue = 105; - return; - } - if(strcmp(color, "slate gray") == 0) { - rgb->red = 112; - rgb->green = 128; - rgb->blue = 144; - return; - } - if(strcmp(color, "SlateGray") == 0) { - rgb->red = 112; - rgb->green = 128; - rgb->blue = 144; - return; - } - if(strcmp(color, "slate grey") == 0) { - rgb->red = 112; - rgb->green = 128; - rgb->blue = 144; - return; - } - if(strcmp(color, "SlateGrey") == 0) { - rgb->red = 112; - rgb->green = 128; - rgb->blue = 144; - return; - } - if(strcmp(color, "light slate gray") == 0) { - rgb->red = 119; - rgb->green = 136; - rgb->blue = 153; - return; - } - if(strcmp(color, "LightSlateGray") == 0) { - rgb->red = 119; - rgb->green = 136; - rgb->blue = 153; - return; - } - if(strcmp(color, "light slate grey") == 0) { - rgb->red = 119; - rgb->green = 136; - rgb->blue = 153; - return; - } - if(strcmp(color, "LightSlateGrey") == 0) { - rgb->red = 119; - rgb->green = 136; - rgb->blue = 153; - return; - } - if(strcmp(color, "gray") == 0) { - rgb->red = 190; - rgb->green = 190; - rgb->blue = 190; - return; - } - if(strcmp(color, "grey") == 0) { - rgb->red = 190; - rgb->green = 190; - rgb->blue = 190; - return; - } - if(strcmp(color, "x11 gray") == 0) { - rgb->red = 190; - rgb->green = 190; - rgb->blue = 190; - return; - } - if(strcmp(color, "X11Gray") == 0) { - rgb->red = 190; - rgb->green = 190; - rgb->blue = 190; - return; - } - if(strcmp(color, "x11 grey") == 0) { - rgb->red = 190; - rgb->green = 190; - rgb->blue = 190; - return; - } - if(strcmp(color, "X11Grey") == 0) { - rgb->red = 190; - rgb->green = 190; - rgb->blue = 190; - return; - } - if(strcmp(color, "web gray") == 0) { - rgb->red = 128; - rgb->green = 128; - rgb->blue = 128; - return; - } - if(strcmp(color, "WebGray") == 0) { - rgb->red = 128; - rgb->green = 128; - rgb->blue = 128; - return; - } - if(strcmp(color, "web grey") == 0) { - rgb->red = 128; - rgb->green = 128; - rgb->blue = 128; - return; - } - if(strcmp(color, "WebGrey") == 0) { - rgb->red = 128; - rgb->green = 128; - rgb->blue = 128; - return; - } - if(strcmp(color, "light grey") == 0) { - rgb->red = 211; - rgb->green = 211; - rgb->blue = 211; - return; - } - if(strcmp(color, "LightGrey") == 0) { - rgb->red = 211; - rgb->green = 211; - rgb->blue = 211; - return; - } - if(strcmp(color, "light gray") == 0) { - rgb->red = 211; - rgb->green = 211; - rgb->blue = 211; - return; - } - if(strcmp(color, "LightGray") == 0) { - rgb->red = 211; - rgb->green = 211; - rgb->blue = 211; - return; - } - if(strcmp(color, "midnight blue") == 0) { - rgb->red = 25; - rgb->green = 25; - rgb->blue = 112; - return; - } - if(strcmp(color, "MidnightBlue") == 0) { - rgb->red = 25; - rgb->green = 25; - rgb->blue = 112; - return; - } - if(strcmp(color, "navy") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 128; - return; - } - if(strcmp(color, "navy blue") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 128; - return; - } - if(strcmp(color, "NavyBlue") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 128; - return; - } - if(strcmp(color, "cornflower blue") == 0) { - rgb->red = 100; - rgb->green = 149; - rgb->blue = 237; - return; - } - if(strcmp(color, "CornflowerBlue") == 0) { - rgb->red = 100; - rgb->green = 149; - rgb->blue = 237; - return; - } - if(strcmp(color, "dark slate blue") == 0) { - rgb->red = 72; - rgb->green = 61; - rgb->blue = 139; - return; - } - if(strcmp(color, "DarkSlateBlue") == 0) { - rgb->red = 72; - rgb->green = 61; - rgb->blue = 139; - return; - } - if(strcmp(color, "slate blue") == 0) { - rgb->red = 106; - rgb->green = 90; - rgb->blue = 205; - return; - } - if(strcmp(color, "SlateBlue") == 0) { - rgb->red = 106; - rgb->green = 90; - rgb->blue = 205; - return; - } - if(strcmp(color, "medium slate blue") == 0) { - rgb->red = 123; - rgb->green = 104; - rgb->blue = 238; - return; - } - if(strcmp(color, "MediumSlateBlue") == 0) { - rgb->red = 123; - rgb->green = 104; - rgb->blue = 238; - return; - } - if(strcmp(color, "light slate blue") == 0) { - rgb->red = 132; - rgb->green = 112; - rgb->blue = 255; - return; - } - if(strcmp(color, "LightSlateBlue") == 0) { - rgb->red = 132; - rgb->green = 112; - rgb->blue = 255; - return; - } - if(strcmp(color, "medium blue") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 205; - return; - } - if(strcmp(color, "MediumBlue") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 205; - return; - } - if(strcmp(color, "royal blue") == 0) { - rgb->red = 65; - rgb->green = 105; - rgb->blue = 225; - return; - } - if(strcmp(color, "RoyalBlue") == 0) { - rgb->red = 65; - rgb->green = 105; - rgb->blue = 225; - return; - } - if(strcmp(color, "blue") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 255; - return; - } - if(strcmp(color, "dodger blue") == 0) { - rgb->red = 30; - rgb->green = 144; - rgb->blue = 255; - return; - } - if(strcmp(color, "DodgerBlue") == 0) { - rgb->red = 30; - rgb->green = 144; - rgb->blue = 255; - return; - } - if(strcmp(color, "deep sky blue") == 0) { - rgb->red = 0; - rgb->green = 191; - rgb->blue = 255; - return; - } - if(strcmp(color, "DeepSkyBlue") == 0) { - rgb->red = 0; - rgb->green = 191; - rgb->blue = 255; - return; - } - if(strcmp(color, "sky blue") == 0) { - rgb->red = 135; - rgb->green = 206; - rgb->blue = 235; - return; - } - if(strcmp(color, "SkyBlue") == 0) { - rgb->red = 135; - rgb->green = 206; - rgb->blue = 235; - return; - } - if(strcmp(color, "light sky blue") == 0) { - rgb->red = 135; - rgb->green = 206; - rgb->blue = 250; - return; - } - if(strcmp(color, "LightSkyBlue") == 0) { - rgb->red = 135; - rgb->green = 206; - rgb->blue = 250; - return; - } - if(strcmp(color, "steel blue") == 0) { - rgb->red = 70; - rgb->green = 130; - rgb->blue = 180; - return; - } - if(strcmp(color, "SteelBlue") == 0) { - rgb->red = 70; - rgb->green = 130; - rgb->blue = 180; - return; - } - if(strcmp(color, "light steel blue") == 0) { - rgb->red = 176; - rgb->green = 196; - rgb->blue = 222; - return; - } - if(strcmp(color, "LightSteelBlue") == 0) { - rgb->red = 176; - rgb->green = 196; - rgb->blue = 222; - return; - } - if(strcmp(color, "light blue") == 0) { - rgb->red = 173; - rgb->green = 216; - rgb->blue = 230; - return; - } - if(strcmp(color, "LightBlue") == 0) { - rgb->red = 173; - rgb->green = 216; - rgb->blue = 230; - return; - } - if(strcmp(color, "powder blue") == 0) { - rgb->red = 176; - rgb->green = 224; - rgb->blue = 230; - return; - } - if(strcmp(color, "PowderBlue") == 0) { - rgb->red = 176; - rgb->green = 224; - rgb->blue = 230; - return; - } - if(strcmp(color, "pale turquoise") == 0) { - rgb->red = 175; - rgb->green = 238; - rgb->blue = 238; - return; - } - if(strcmp(color, "PaleTurquoise") == 0) { - rgb->red = 175; - rgb->green = 238; - rgb->blue = 238; - return; - } - if(strcmp(color, "dark turquoise") == 0) { - rgb->red = 0; - rgb->green = 206; - rgb->blue = 209; - return; - } - if(strcmp(color, "DarkTurquoise") == 0) { - rgb->red = 0; - rgb->green = 206; - rgb->blue = 209; - return; - } - if(strcmp(color, "medium turquoise") == 0) { - rgb->red = 72; - rgb->green = 209; - rgb->blue = 204; - return; - } - if(strcmp(color, "MediumTurquoise") == 0) { - rgb->red = 72; - rgb->green = 209; - rgb->blue = 204; - return; - } - if(strcmp(color, "turquoise") == 0) { - rgb->red = 64; - rgb->green = 224; - rgb->blue = 208; - return; - } - if(strcmp(color, "cyan") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "aqua") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "light cyan") == 0) { - rgb->red = 224; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "LightCyan") == 0) { - rgb->red = 224; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "cadet blue") == 0) { - rgb->red = 95; - rgb->green = 158; - rgb->blue = 160; - return; - } - if(strcmp(color, "CadetBlue") == 0) { - rgb->red = 95; - rgb->green = 158; - rgb->blue = 160; - return; - } - if(strcmp(color, "medium aquamarine") == 0) { - rgb->red = 102; - rgb->green = 205; - rgb->blue = 170; - return; - } - if(strcmp(color, "MediumAquamarine") == 0) { - rgb->red = 102; - rgb->green = 205; - rgb->blue = 170; - return; - } - if(strcmp(color, "aquamarine") == 0) { - rgb->red = 127; - rgb->green = 255; - rgb->blue = 212; - return; - } - if(strcmp(color, "dark green") == 0) { - rgb->red = 0; - rgb->green = 100; - rgb->blue = 0; - return; - } - if(strcmp(color, "DarkGreen") == 0) { - rgb->red = 0; - rgb->green = 100; - rgb->blue = 0; - return; - } - if(strcmp(color, "dark olive green") == 0) { - rgb->red = 85; - rgb->green = 107; - rgb->blue = 47; - return; - } - if(strcmp(color, "DarkOliveGreen") == 0) { - rgb->red = 85; - rgb->green = 107; - rgb->blue = 47; - return; - } - if(strcmp(color, "dark sea green") == 0) { - rgb->red = 143; - rgb->green = 188; - rgb->blue = 143; - return; - } - if(strcmp(color, "DarkSeaGreen") == 0) { - rgb->red = 143; - rgb->green = 188; - rgb->blue = 143; - return; - } - if(strcmp(color, "sea green") == 0) { - rgb->red = 46; - rgb->green = 139; - rgb->blue = 87; - return; - } - if(strcmp(color, "SeaGreen") == 0) { - rgb->red = 46; - rgb->green = 139; - rgb->blue = 87; - return; - } - if(strcmp(color, "medium sea green") == 0) { - rgb->red = 60; - rgb->green = 179; - rgb->blue = 113; - return; - } - if(strcmp(color, "MediumSeaGreen") == 0) { - rgb->red = 60; - rgb->green = 179; - rgb->blue = 113; - return; - } - if(strcmp(color, "light sea green") == 0) { - rgb->red = 32; - rgb->green = 178; - rgb->blue = 170; - return; - } - if(strcmp(color, "LightSeaGreen") == 0) { - rgb->red = 32; - rgb->green = 178; - rgb->blue = 170; - return; - } - if(strcmp(color, "pale green") == 0) { - rgb->red = 152; - rgb->green = 251; - rgb->blue = 152; - return; - } - if(strcmp(color, "PaleGreen") == 0) { - rgb->red = 152; - rgb->green = 251; - rgb->blue = 152; - return; - } - if(strcmp(color, "spring green") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 127; - return; - } - if(strcmp(color, "SpringGreen") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 127; - return; - } - if(strcmp(color, "lawn green") == 0) { - rgb->red = 124; - rgb->green = 252; - rgb->blue = 0; - return; - } - if(strcmp(color, "LawnGreen") == 0) { - rgb->red = 124; - rgb->green = 252; - rgb->blue = 0; - return; - } - if(strcmp(color, "green") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 0; - return; - } - if(strcmp(color, "lime") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 0; - return; - } - if(strcmp(color, "x11 green") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 0; - return; - } - if(strcmp(color, "X11Green") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 0; - return; - } - if(strcmp(color, "web green") == 0) { - rgb->red = 0; - rgb->green = 128; - rgb->blue = 0; - return; - } - if(strcmp(color, "WebGreen") == 0) { - rgb->red = 0; - rgb->green = 128; - rgb->blue = 0; - return; - } - if(strcmp(color, "chartreuse") == 0) { - rgb->red = 127; - rgb->green = 255; - rgb->blue = 0; - return; - } - if(strcmp(color, "medium spring green") == 0) { - rgb->red = 0; - rgb->green = 250; - rgb->blue = 154; - return; - } - if(strcmp(color, "MediumSpringGreen") == 0) { - rgb->red = 0; - rgb->green = 250; - rgb->blue = 154; - return; - } - if(strcmp(color, "green yellow") == 0) { - rgb->red = 173; - rgb->green = 255; - rgb->blue = 47; - return; - } - if(strcmp(color, "GreenYellow") == 0) { - rgb->red = 173; - rgb->green = 255; - rgb->blue = 47; - return; - } - if(strcmp(color, "lime green") == 0) { - rgb->red = 50; - rgb->green = 205; - rgb->blue = 50; - return; - } - if(strcmp(color, "LimeGreen") == 0) { - rgb->red = 50; - rgb->green = 205; - rgb->blue = 50; - return; - } - if(strcmp(color, "yellow green") == 0) { - rgb->red = 154; - rgb->green = 205; - rgb->blue = 50; - return; - } - if(strcmp(color, "YellowGreen") == 0) { - rgb->red = 154; - rgb->green = 205; - rgb->blue = 50; - return; - } - if(strcmp(color, "forest green") == 0) { - rgb->red = 34; - rgb->green = 139; - rgb->blue = 34; - return; - } - if(strcmp(color, "ForestGreen") == 0) { - rgb->red = 34; - rgb->green = 139; - rgb->blue = 34; - return; - } - if(strcmp(color, "olive drab") == 0) { - rgb->red = 107; - rgb->green = 142; - rgb->blue = 35; - return; - } - if(strcmp(color, "OliveDrab") == 0) { - rgb->red = 107; - rgb->green = 142; - rgb->blue = 35; - return; - } - if(strcmp(color, "dark khaki") == 0) { - rgb->red = 189; - rgb->green = 183; - rgb->blue = 107; - return; - } - if(strcmp(color, "DarkKhaki") == 0) { - rgb->red = 189; - rgb->green = 183; - rgb->blue = 107; - return; - } - if(strcmp(color, "khaki") == 0) { - rgb->red = 240; - rgb->green = 230; - rgb->blue = 140; - return; - } - if(strcmp(color, "pale goldenrod") == 0) { - rgb->red = 238; - rgb->green = 232; - rgb->blue = 170; - return; - } - if(strcmp(color, "PaleGoldenrod") == 0) { - rgb->red = 238; - rgb->green = 232; - rgb->blue = 170; - return; - } - if(strcmp(color, "light goldenrod yellow") == 0) { - rgb->red = 250; - rgb->green = 250; - rgb->blue = 210; - return; - } - if(strcmp(color, "LightGoldenrodYellow") == 0) { - rgb->red = 250; - rgb->green = 250; - rgb->blue = 210; - return; - } - if(strcmp(color, "light yellow") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 224; - return; - } - if(strcmp(color, "LightYellow") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 224; - return; - } - if(strcmp(color, "yellow") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 0; - return; - } - if(strcmp(color, "gold") == 0) { - rgb->red = 255; - rgb->green = 215; - rgb->blue = 0; - return; - } - if(strcmp(color, "light goldenrod") == 0) { - rgb->red = 238; - rgb->green = 221; - rgb->blue = 130; - return; - } - if(strcmp(color, "LightGoldenrod") == 0) { - rgb->red = 238; - rgb->green = 221; - rgb->blue = 130; - return; - } - if(strcmp(color, "goldenrod") == 0) { - rgb->red = 218; - rgb->green = 165; - rgb->blue = 32; - return; - } - if(strcmp(color, "dark goldenrod") == 0) { - rgb->red = 184; - rgb->green = 134; - rgb->blue = 11; - return; - } - if(strcmp(color, "DarkGoldenrod") == 0) { - rgb->red = 184; - rgb->green = 134; - rgb->blue = 11; - return; - } - if(strcmp(color, "rosy brown") == 0) { - rgb->red = 188; - rgb->green = 143; - rgb->blue = 143; - return; - } - if(strcmp(color, "RosyBrown") == 0) { - rgb->red = 188; - rgb->green = 143; - rgb->blue = 143; - return; - } - if(strcmp(color, "indian red") == 0) { - rgb->red = 205; - rgb->green = 92; - rgb->blue = 92; - return; - } - if(strcmp(color, "IndianRed") == 0) { - rgb->red = 205; - rgb->green = 92; - rgb->blue = 92; - return; - } - if(strcmp(color, "saddle brown") == 0) { - rgb->red = 139; - rgb->green = 69; - rgb->blue = 19; - return; - } - if(strcmp(color, "SaddleBrown") == 0) { - rgb->red = 139; - rgb->green = 69; - rgb->blue = 19; - return; - } - if(strcmp(color, "sienna") == 0) { - rgb->red = 160; - rgb->green = 82; - rgb->blue = 45; - return; - } - if(strcmp(color, "peru") == 0) { - rgb->red = 205; - rgb->green = 133; - rgb->blue = 63; - return; - } - if(strcmp(color, "burlywood") == 0) { - rgb->red = 222; - rgb->green = 184; - rgb->blue = 135; - return; - } - if(strcmp(color, "beige") == 0) { - rgb->red = 245; - rgb->green = 245; - rgb->blue = 220; - return; - } - if(strcmp(color, "wheat") == 0) { - rgb->red = 245; - rgb->green = 222; - rgb->blue = 179; - return; - } - if(strcmp(color, "sandy brown") == 0) { - rgb->red = 244; - rgb->green = 164; - rgb->blue = 96; - return; - } - if(strcmp(color, "SandyBrown") == 0) { - rgb->red = 244; - rgb->green = 164; - rgb->blue = 96; - return; - } - if(strcmp(color, "tan") == 0) { - rgb->red = 210; - rgb->green = 180; - rgb->blue = 140; - return; - } - if(strcmp(color, "chocolate") == 0) { - rgb->red = 210; - rgb->green = 105; - rgb->blue = 30; - return; - } - if(strcmp(color, "firebrick") == 0) { - rgb->red = 178; - rgb->green = 34; - rgb->blue = 34; - return; - } - if(strcmp(color, "brown") == 0) { - rgb->red = 165; - rgb->green = 42; - rgb->blue = 42; - return; - } - if(strcmp(color, "dark salmon") == 0) { - rgb->red = 233; - rgb->green = 150; - rgb->blue = 122; - return; - } - if(strcmp(color, "DarkSalmon") == 0) { - rgb->red = 233; - rgb->green = 150; - rgb->blue = 122; - return; - } - if(strcmp(color, "salmon") == 0) { - rgb->red = 250; - rgb->green = 128; - rgb->blue = 114; - return; - } - if(strcmp(color, "light salmon") == 0) { - rgb->red = 255; - rgb->green = 160; - rgb->blue = 122; - return; - } - if(strcmp(color, "LightSalmon") == 0) { - rgb->red = 255; - rgb->green = 160; - rgb->blue = 122; - return; - } - if(strcmp(color, "orange") == 0) { - rgb->red = 255; - rgb->green = 165; - rgb->blue = 0; - return; - } - if(strcmp(color, "dark orange") == 0) { - rgb->red = 255; - rgb->green = 140; - rgb->blue = 0; - return; - } - if(strcmp(color, "DarkOrange") == 0) { - rgb->red = 255; - rgb->green = 140; - rgb->blue = 0; - return; - } - if(strcmp(color, "coral") == 0) { - rgb->red = 255; - rgb->green = 127; - rgb->blue = 80; - return; - } - if(strcmp(color, "light coral") == 0) { - rgb->red = 240; - rgb->green = 128; - rgb->blue = 128; - return; - } - if(strcmp(color, "LightCoral") == 0) { - rgb->red = 240; - rgb->green = 128; - rgb->blue = 128; - return; - } - if(strcmp(color, "tomato") == 0) { - rgb->red = 255; - rgb->green = 99; - rgb->blue = 71; - return; - } - if(strcmp(color, "orange red") == 0) { - rgb->red = 255; - rgb->green = 69; - rgb->blue = 0; - return; - } - if(strcmp(color, "OrangeRed") == 0) { - rgb->red = 255; - rgb->green = 69; - rgb->blue = 0; - return; - } - if(strcmp(color, "red") == 0) { - rgb->red = 255; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "hot pink") == 0) { - rgb->red = 255; - rgb->green = 105; - rgb->blue = 180; - return; - } - if(strcmp(color, "HotPink") == 0) { - rgb->red = 255; - rgb->green = 105; - rgb->blue = 180; - return; - } - if(strcmp(color, "deep pink") == 0) { - rgb->red = 255; - rgb->green = 20; - rgb->blue = 147; - return; - } - if(strcmp(color, "DeepPink") == 0) { - rgb->red = 255; - rgb->green = 20; - rgb->blue = 147; - return; - } - if(strcmp(color, "pink") == 0) { - rgb->red = 255; - rgb->green = 192; - rgb->blue = 203; - return; - } - if(strcmp(color, "light pink") == 0) { - rgb->red = 255; - rgb->green = 182; - rgb->blue = 193; - return; - } - if(strcmp(color, "LightPink") == 0) { - rgb->red = 255; - rgb->green = 182; - rgb->blue = 193; - return; - } - if(strcmp(color, "pale violet red") == 0) { - rgb->red = 219; - rgb->green = 112; - rgb->blue = 147; - return; - } - if(strcmp(color, "PaleVioletRed") == 0) { - rgb->red = 219; - rgb->green = 112; - rgb->blue = 147; - return; - } - if(strcmp(color, "maroon") == 0) { - rgb->red = 176; - rgb->green = 48; - rgb->blue = 96; - return; - } - if(strcmp(color, "x11 maroon") == 0) { - rgb->red = 176; - rgb->green = 48; - rgb->blue = 96; - return; - } - if(strcmp(color, "X11Maroon") == 0) { - rgb->red = 176; - rgb->green = 48; - rgb->blue = 96; - return; - } - if(strcmp(color, "web maroon") == 0) { - rgb->red = 128; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "WebMaroon") == 0) { - rgb->red = 128; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "medium violet red") == 0) { - rgb->red = 199; - rgb->green = 21; - rgb->blue = 133; - return; - } - if(strcmp(color, "MediumVioletRed") == 0) { - rgb->red = 199; - rgb->green = 21; - rgb->blue = 133; - return; - } - if(strcmp(color, "violet red") == 0) { - rgb->red = 208; - rgb->green = 32; - rgb->blue = 144; - return; - } - if(strcmp(color, "VioletRed") == 0) { - rgb->red = 208; - rgb->green = 32; - rgb->blue = 144; - return; - } - if(strcmp(color, "magenta") == 0) { - rgb->red = 255; - rgb->green = 0; - rgb->blue = 255; - return; - } - if(strcmp(color, "fuchsia") == 0) { - rgb->red = 255; - rgb->green = 0; - rgb->blue = 255; - return; - } - if(strcmp(color, "violet") == 0) { - rgb->red = 238; - rgb->green = 130; - rgb->blue = 238; - return; - } - if(strcmp(color, "plum") == 0) { - rgb->red = 221; - rgb->green = 160; - rgb->blue = 221; - return; - } - if(strcmp(color, "orchid") == 0) { - rgb->red = 218; - rgb->green = 112; - rgb->blue = 214; - return; - } - if(strcmp(color, "medium orchid") == 0) { - rgb->red = 186; - rgb->green = 85; - rgb->blue = 211; - return; - } - if(strcmp(color, "MediumOrchid") == 0) { - rgb->red = 186; - rgb->green = 85; - rgb->blue = 211; - return; - } - if(strcmp(color, "dark orchid") == 0) { - rgb->red = 153; - rgb->green = 50; - rgb->blue = 204; - return; - } - if(strcmp(color, "DarkOrchid") == 0) { - rgb->red = 153; - rgb->green = 50; - rgb->blue = 204; - return; - } - if(strcmp(color, "dark violet") == 0) { - rgb->red = 148; - rgb->green = 0; - rgb->blue = 211; - return; - } - if(strcmp(color, "DarkViolet") == 0) { - rgb->red = 148; - rgb->green = 0; - rgb->blue = 211; - return; - } - if(strcmp(color, "blue violet") == 0) { - rgb->red = 138; - rgb->green = 43; - rgb->blue = 226; - return; - } - if(strcmp(color, "BlueViolet") == 0) { - rgb->red = 138; - rgb->green = 43; - rgb->blue = 226; - return; - } - if(strcmp(color, "purple") == 0) { - rgb->red = 160; - rgb->green = 32; - rgb->blue = 240; - return; - } - if(strcmp(color, "x11 purple") == 0) { - rgb->red = 160; - rgb->green = 32; - rgb->blue = 240; - return; - } - if(strcmp(color, "X11Purple") == 0) { - rgb->red = 160; - rgb->green = 32; - rgb->blue = 240; - return; - } - if(strcmp(color, "web purple") == 0) { - rgb->red = 128; - rgb->green = 0; - rgb->blue = 128; - return; - } - if(strcmp(color, "WebPurple") == 0) { - rgb->red = 128; - rgb->green = 0; - rgb->blue = 128; - return; - } - if(strcmp(color, "medium purple") == 0) { - rgb->red = 147; - rgb->green = 112; - rgb->blue = 219; - return; - } - if(strcmp(color, "MediumPurple") == 0) { - rgb->red = 147; - rgb->green = 112; - rgb->blue = 219; - return; - } - if(strcmp(color, "thistle") == 0) { - rgb->red = 216; - rgb->green = 191; - rgb->blue = 216; - return; - } - if(strcmp(color, "snow1") == 0) { - rgb->red = 255; - rgb->green = 250; - rgb->blue = 250; - return; - } - if(strcmp(color, "snow2") == 0) { - rgb->red = 238; - rgb->green = 233; - rgb->blue = 233; - return; - } - if(strcmp(color, "snow3") == 0) { - rgb->red = 205; - rgb->green = 201; - rgb->blue = 201; - return; - } - if(strcmp(color, "snow4") == 0) { - rgb->red = 139; - rgb->green = 137; - rgb->blue = 137; - return; - } - if(strcmp(color, "seashell1") == 0) { - rgb->red = 255; - rgb->green = 245; - rgb->blue = 238; - return; - } - if(strcmp(color, "seashell2") == 0) { - rgb->red = 238; - rgb->green = 229; - rgb->blue = 222; - return; - } - if(strcmp(color, "seashell3") == 0) { - rgb->red = 205; - rgb->green = 197; - rgb->blue = 191; - return; - } - if(strcmp(color, "seashell4") == 0) { - rgb->red = 139; - rgb->green = 134; - rgb->blue = 130; - return; - } - if(strcmp(color, "AntiqueWhite1") == 0) { - rgb->red = 255; - rgb->green = 239; - rgb->blue = 219; - return; - } - if(strcmp(color, "AntiqueWhite2") == 0) { - rgb->red = 238; - rgb->green = 223; - rgb->blue = 204; - return; - } - if(strcmp(color, "AntiqueWhite3") == 0) { - rgb->red = 205; - rgb->green = 192; - rgb->blue = 176; - return; - } - if(strcmp(color, "AntiqueWhite4") == 0) { - rgb->red = 139; - rgb->green = 131; - rgb->blue = 120; - return; - } - if(strcmp(color, "bisque1") == 0) { - rgb->red = 255; - rgb->green = 228; - rgb->blue = 196; - return; - } - if(strcmp(color, "bisque2") == 0) { - rgb->red = 238; - rgb->green = 213; - rgb->blue = 183; - return; - } - if(strcmp(color, "bisque3") == 0) { - rgb->red = 205; - rgb->green = 183; - rgb->blue = 158; - return; - } - if(strcmp(color, "bisque4") == 0) { - rgb->red = 139; - rgb->green = 125; - rgb->blue = 107; - return; - } - if(strcmp(color, "PeachPuff1") == 0) { - rgb->red = 255; - rgb->green = 218; - rgb->blue = 185; - return; - } - if(strcmp(color, "PeachPuff2") == 0) { - rgb->red = 238; - rgb->green = 203; - rgb->blue = 173; - return; - } - if(strcmp(color, "PeachPuff3") == 0) { - rgb->red = 205; - rgb->green = 175; - rgb->blue = 149; - return; - } - if(strcmp(color, "PeachPuff4") == 0) { - rgb->red = 139; - rgb->green = 119; - rgb->blue = 101; - return; - } - if(strcmp(color, "NavajoWhite1") == 0) { - rgb->red = 255; - rgb->green = 222; - rgb->blue = 173; - return; - } - if(strcmp(color, "NavajoWhite2") == 0) { - rgb->red = 238; - rgb->green = 207; - rgb->blue = 161; - return; - } - if(strcmp(color, "NavajoWhite3") == 0) { - rgb->red = 205; - rgb->green = 179; - rgb->blue = 139; - return; - } - if(strcmp(color, "NavajoWhite4") == 0) { - rgb->red = 139; - rgb->green = 121; - rgb->blue = 94; - return; - } - if(strcmp(color, "LemonChiffon1") == 0) { - rgb->red = 255; - rgb->green = 250; - rgb->blue = 205; - return; - } - if(strcmp(color, "LemonChiffon2") == 0) { - rgb->red = 238; - rgb->green = 233; - rgb->blue = 191; - return; - } - if(strcmp(color, "LemonChiffon3") == 0) { - rgb->red = 205; - rgb->green = 201; - rgb->blue = 165; - return; - } - if(strcmp(color, "LemonChiffon4") == 0) { - rgb->red = 139; - rgb->green = 137; - rgb->blue = 112; - return; - } - if(strcmp(color, "cornsilk1") == 0) { - rgb->red = 255; - rgb->green = 248; - rgb->blue = 220; - return; - } - if(strcmp(color, "cornsilk2") == 0) { - rgb->red = 238; - rgb->green = 232; - rgb->blue = 205; - return; - } - if(strcmp(color, "cornsilk3") == 0) { - rgb->red = 205; - rgb->green = 200; - rgb->blue = 177; - return; - } - if(strcmp(color, "cornsilk4") == 0) { - rgb->red = 139; - rgb->green = 136; - rgb->blue = 120; - return; - } - if(strcmp(color, "ivory1") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 240; - return; - } - if(strcmp(color, "ivory2") == 0) { - rgb->red = 238; - rgb->green = 238; - rgb->blue = 224; - return; - } - if(strcmp(color, "ivory3") == 0) { - rgb->red = 205; - rgb->green = 205; - rgb->blue = 193; - return; - } - if(strcmp(color, "ivory4") == 0) { - rgb->red = 139; - rgb->green = 139; - rgb->blue = 131; - return; - } - if(strcmp(color, "honeydew1") == 0) { - rgb->red = 240; - rgb->green = 255; - rgb->blue = 240; - return; - } - if(strcmp(color, "honeydew2") == 0) { - rgb->red = 224; - rgb->green = 238; - rgb->blue = 224; - return; - } - if(strcmp(color, "honeydew3") == 0) { - rgb->red = 193; - rgb->green = 205; - rgb->blue = 193; - return; - } - if(strcmp(color, "honeydew4") == 0) { - rgb->red = 131; - rgb->green = 139; - rgb->blue = 131; - return; - } - if(strcmp(color, "LavenderBlush1") == 0) { - rgb->red = 255; - rgb->green = 240; - rgb->blue = 245; - return; - } - if(strcmp(color, "LavenderBlush2") == 0) { - rgb->red = 238; - rgb->green = 224; - rgb->blue = 229; - return; - } - if(strcmp(color, "LavenderBlush3") == 0) { - rgb->red = 205; - rgb->green = 193; - rgb->blue = 197; - return; - } - if(strcmp(color, "LavenderBlush4") == 0) { - rgb->red = 139; - rgb->green = 131; - rgb->blue = 134; - return; - } - if(strcmp(color, "MistyRose1") == 0) { - rgb->red = 255; - rgb->green = 228; - rgb->blue = 225; - return; - } - if(strcmp(color, "MistyRose2") == 0) { - rgb->red = 238; - rgb->green = 213; - rgb->blue = 210; - return; - } - if(strcmp(color, "MistyRose3") == 0) { - rgb->red = 205; - rgb->green = 183; - rgb->blue = 181; - return; - } - if(strcmp(color, "MistyRose4") == 0) { - rgb->red = 139; - rgb->green = 125; - rgb->blue = 123; - return; - } - if(strcmp(color, "azure1") == 0) { - rgb->red = 240; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "azure2") == 0) { - rgb->red = 224; - rgb->green = 238; - rgb->blue = 238; - return; - } - if(strcmp(color, "azure3") == 0) { - rgb->red = 193; - rgb->green = 205; - rgb->blue = 205; - return; - } - if(strcmp(color, "azure4") == 0) { - rgb->red = 131; - rgb->green = 139; - rgb->blue = 139; - return; - } - if(strcmp(color, "SlateBlue1") == 0) { - rgb->red = 131; - rgb->green = 111; - rgb->blue = 255; - return; - } - if(strcmp(color, "SlateBlue2") == 0) { - rgb->red = 122; - rgb->green = 103; - rgb->blue = 238; - return; - } - if(strcmp(color, "SlateBlue3") == 0) { - rgb->red = 105; - rgb->green = 89; - rgb->blue = 205; - return; - } - if(strcmp(color, "SlateBlue4") == 0) { - rgb->red = 71; - rgb->green = 60; - rgb->blue = 139; - return; - } - if(strcmp(color, "RoyalBlue1") == 0) { - rgb->red = 72; - rgb->green = 118; - rgb->blue = 255; - return; - } - if(strcmp(color, "RoyalBlue2") == 0) { - rgb->red = 67; - rgb->green = 110; - rgb->blue = 238; - return; - } - if(strcmp(color, "RoyalBlue3") == 0) { - rgb->red = 58; - rgb->green = 95; - rgb->blue = 205; - return; - } - if(strcmp(color, "RoyalBlue4") == 0) { - rgb->red = 39; - rgb->green = 64; - rgb->blue = 139; - return; - } - if(strcmp(color, "blue1") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 255; - return; - } - if(strcmp(color, "blue2") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 238; - return; - } - if(strcmp(color, "blue3") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 205; - return; - } - if(strcmp(color, "blue4") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 139; - return; - } - if(strcmp(color, "DodgerBlue1") == 0) { - rgb->red = 30; - rgb->green = 144; - rgb->blue = 255; - return; - } - if(strcmp(color, "DodgerBlue2") == 0) { - rgb->red = 28; - rgb->green = 134; - rgb->blue = 238; - return; - } - if(strcmp(color, "DodgerBlue3") == 0) { - rgb->red = 24; - rgb->green = 116; - rgb->blue = 205; - return; - } - if(strcmp(color, "DodgerBlue4") == 0) { - rgb->red = 16; - rgb->green = 78; - rgb->blue = 139; - return; - } - if(strcmp(color, "SteelBlue1") == 0) { - rgb->red = 99; - rgb->green = 184; - rgb->blue = 255; - return; - } - if(strcmp(color, "SteelBlue2") == 0) { - rgb->red = 92; - rgb->green = 172; - rgb->blue = 238; - return; - } - if(strcmp(color, "SteelBlue3") == 0) { - rgb->red = 79; - rgb->green = 148; - rgb->blue = 205; - return; - } - if(strcmp(color, "SteelBlue4") == 0) { - rgb->red = 54; - rgb->green = 100; - rgb->blue = 139; - return; - } - if(strcmp(color, "DeepSkyBlue1") == 0) { - rgb->red = 0; - rgb->green = 191; - rgb->blue = 255; - return; - } - if(strcmp(color, "DeepSkyBlue2") == 0) { - rgb->red = 0; - rgb->green = 178; - rgb->blue = 238; - return; - } - if(strcmp(color, "DeepSkyBlue3") == 0) { - rgb->red = 0; - rgb->green = 154; - rgb->blue = 205; - return; - } - if(strcmp(color, "DeepSkyBlue4") == 0) { - rgb->red = 0; - rgb->green = 104; - rgb->blue = 139; - return; - } - if(strcmp(color, "SkyBlue1") == 0) { - rgb->red = 135; - rgb->green = 206; - rgb->blue = 255; - return; - } - if(strcmp(color, "SkyBlue2") == 0) { - rgb->red = 126; - rgb->green = 192; - rgb->blue = 238; - return; - } - if(strcmp(color, "SkyBlue3") == 0) { - rgb->red = 108; - rgb->green = 166; - rgb->blue = 205; - return; - } - if(strcmp(color, "SkyBlue4") == 0) { - rgb->red = 74; - rgb->green = 112; - rgb->blue = 139; - return; - } - if(strcmp(color, "LightSkyBlue1") == 0) { - rgb->red = 176; - rgb->green = 226; - rgb->blue = 255; - return; - } - if(strcmp(color, "LightSkyBlue2") == 0) { - rgb->red = 164; - rgb->green = 211; - rgb->blue = 238; - return; - } - if(strcmp(color, "LightSkyBlue3") == 0) { - rgb->red = 141; - rgb->green = 182; - rgb->blue = 205; - return; - } - if(strcmp(color, "LightSkyBlue4") == 0) { - rgb->red = 96; - rgb->green = 123; - rgb->blue = 139; - return; - } - if(strcmp(color, "SlateGray1") == 0) { - rgb->red = 198; - rgb->green = 226; - rgb->blue = 255; - return; - } - if(strcmp(color, "SlateGray2") == 0) { - rgb->red = 185; - rgb->green = 211; - rgb->blue = 238; - return; - } - if(strcmp(color, "SlateGray3") == 0) { - rgb->red = 159; - rgb->green = 182; - rgb->blue = 205; - return; - } - if(strcmp(color, "SlateGray4") == 0) { - rgb->red = 108; - rgb->green = 123; - rgb->blue = 139; - return; - } - if(strcmp(color, "LightSteelBlue1") == 0) { - rgb->red = 202; - rgb->green = 225; - rgb->blue = 255; - return; - } - if(strcmp(color, "LightSteelBlue2") == 0) { - rgb->red = 188; - rgb->green = 210; - rgb->blue = 238; - return; - } - if(strcmp(color, "LightSteelBlue3") == 0) { - rgb->red = 162; - rgb->green = 181; - rgb->blue = 205; - return; - } - if(strcmp(color, "LightSteelBlue4") == 0) { - rgb->red = 110; - rgb->green = 123; - rgb->blue = 139; - return; - } - if(strcmp(color, "LightBlue1") == 0) { - rgb->red = 191; - rgb->green = 239; - rgb->blue = 255; - return; - } - if(strcmp(color, "LightBlue2") == 0) { - rgb->red = 178; - rgb->green = 223; - rgb->blue = 238; - return; - } - if(strcmp(color, "LightBlue3") == 0) { - rgb->red = 154; - rgb->green = 192; - rgb->blue = 205; - return; - } - if(strcmp(color, "LightBlue4") == 0) { - rgb->red = 104; - rgb->green = 131; - rgb->blue = 139; - return; - } - if(strcmp(color, "LightCyan1") == 0) { - rgb->red = 224; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "LightCyan2") == 0) { - rgb->red = 209; - rgb->green = 238; - rgb->blue = 238; - return; - } - if(strcmp(color, "LightCyan3") == 0) { - rgb->red = 180; - rgb->green = 205; - rgb->blue = 205; - return; - } - if(strcmp(color, "LightCyan4") == 0) { - rgb->red = 122; - rgb->green = 139; - rgb->blue = 139; - return; - } - if(strcmp(color, "PaleTurquoise1") == 0) { - rgb->red = 187; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "PaleTurquoise2") == 0) { - rgb->red = 174; - rgb->green = 238; - rgb->blue = 238; - return; - } - if(strcmp(color, "PaleTurquoise3") == 0) { - rgb->red = 150; - rgb->green = 205; - rgb->blue = 205; - return; - } - if(strcmp(color, "PaleTurquoise4") == 0) { - rgb->red = 102; - rgb->green = 139; - rgb->blue = 139; - return; - } - if(strcmp(color, "CadetBlue1") == 0) { - rgb->red = 152; - rgb->green = 245; - rgb->blue = 255; - return; - } - if(strcmp(color, "CadetBlue2") == 0) { - rgb->red = 142; - rgb->green = 229; - rgb->blue = 238; - return; - } - if(strcmp(color, "CadetBlue3") == 0) { - rgb->red = 122; - rgb->green = 197; - rgb->blue = 205; - return; - } - if(strcmp(color, "CadetBlue4") == 0) { - rgb->red = 83; - rgb->green = 134; - rgb->blue = 139; - return; - } - if(strcmp(color, "turquoise1") == 0) { - rgb->red = 0; - rgb->green = 245; - rgb->blue = 255; - return; - } - if(strcmp(color, "turquoise2") == 0) { - rgb->red = 0; - rgb->green = 229; - rgb->blue = 238; - return; - } - if(strcmp(color, "turquoise3") == 0) { - rgb->red = 0; - rgb->green = 197; - rgb->blue = 205; - return; - } - if(strcmp(color, "turquoise4") == 0) { - rgb->red = 0; - rgb->green = 134; - rgb->blue = 139; - return; - } - if(strcmp(color, "cyan1") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "cyan2") == 0) { - rgb->red = 0; - rgb->green = 238; - rgb->blue = 238; - return; - } - if(strcmp(color, "cyan3") == 0) { - rgb->red = 0; - rgb->green = 205; - rgb->blue = 205; - return; - } - if(strcmp(color, "cyan4") == 0) { - rgb->red = 0; - rgb->green = 139; - rgb->blue = 139; - return; - } - if(strcmp(color, "DarkSlateGray1") == 0) { - rgb->red = 151; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "DarkSlateGray2") == 0) { - rgb->red = 141; - rgb->green = 238; - rgb->blue = 238; - return; - } - if(strcmp(color, "DarkSlateGray3") == 0) { - rgb->red = 121; - rgb->green = 205; - rgb->blue = 205; - return; - } - if(strcmp(color, "DarkSlateGray4") == 0) { - rgb->red = 82; - rgb->green = 139; - rgb->blue = 139; - return; - } - if(strcmp(color, "aquamarine1") == 0) { - rgb->red = 127; - rgb->green = 255; - rgb->blue = 212; - return; - } - if(strcmp(color, "aquamarine2") == 0) { - rgb->red = 118; - rgb->green = 238; - rgb->blue = 198; - return; - } - if(strcmp(color, "aquamarine3") == 0) { - rgb->red = 102; - rgb->green = 205; - rgb->blue = 170; - return; - } - if(strcmp(color, "aquamarine4") == 0) { - rgb->red = 69; - rgb->green = 139; - rgb->blue = 116; - return; - } - if(strcmp(color, "DarkSeaGreen1") == 0) { - rgb->red = 193; - rgb->green = 255; - rgb->blue = 193; - return; - } - if(strcmp(color, "DarkSeaGreen2") == 0) { - rgb->red = 180; - rgb->green = 238; - rgb->blue = 180; - return; - } - if(strcmp(color, "DarkSeaGreen3") == 0) { - rgb->red = 155; - rgb->green = 205; - rgb->blue = 155; - return; - } - if(strcmp(color, "DarkSeaGreen4") == 0) { - rgb->red = 105; - rgb->green = 139; - rgb->blue = 105; - return; - } - if(strcmp(color, "SeaGreen1") == 0) { - rgb->red = 84; - rgb->green = 255; - rgb->blue = 159; - return; - } - if(strcmp(color, "SeaGreen2") == 0) { - rgb->red = 78; - rgb->green = 238; - rgb->blue = 148; - return; - } - if(strcmp(color, "SeaGreen3") == 0) { - rgb->red = 67; - rgb->green = 205; - rgb->blue = 128; - return; - } - if(strcmp(color, "SeaGreen4") == 0) { - rgb->red = 46; - rgb->green = 139; - rgb->blue = 87; - return; - } - if(strcmp(color, "PaleGreen1") == 0) { - rgb->red = 154; - rgb->green = 255; - rgb->blue = 154; - return; - } - if(strcmp(color, "PaleGreen2") == 0) { - rgb->red = 144; - rgb->green = 238; - rgb->blue = 144; - return; - } - if(strcmp(color, "PaleGreen3") == 0) { - rgb->red = 124; - rgb->green = 205; - rgb->blue = 124; - return; - } - if(strcmp(color, "PaleGreen4") == 0) { - rgb->red = 84; - rgb->green = 139; - rgb->blue = 84; - return; - } - if(strcmp(color, "SpringGreen1") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 127; - return; - } - if(strcmp(color, "SpringGreen2") == 0) { - rgb->red = 0; - rgb->green = 238; - rgb->blue = 118; - return; - } - if(strcmp(color, "SpringGreen3") == 0) { - rgb->red = 0; - rgb->green = 205; - rgb->blue = 102; - return; - } - if(strcmp(color, "SpringGreen4") == 0) { - rgb->red = 0; - rgb->green = 139; - rgb->blue = 69; - return; - } - if(strcmp(color, "green1") == 0) { - rgb->red = 0; - rgb->green = 255; - rgb->blue = 0; - return; - } - if(strcmp(color, "green2") == 0) { - rgb->red = 0; - rgb->green = 238; - rgb->blue = 0; - return; - } - if(strcmp(color, "green3") == 0) { - rgb->red = 0; - rgb->green = 205; - rgb->blue = 0; - return; - } - if(strcmp(color, "green4") == 0) { - rgb->red = 0; - rgb->green = 139; - rgb->blue = 0; - return; - } - if(strcmp(color, "chartreuse1") == 0) { - rgb->red = 127; - rgb->green = 255; - rgb->blue = 0; - return; - } - if(strcmp(color, "chartreuse2") == 0) { - rgb->red = 118; - rgb->green = 238; - rgb->blue = 0; - return; - } - if(strcmp(color, "chartreuse3") == 0) { - rgb->red = 102; - rgb->green = 205; - rgb->blue = 0; - return; - } - if(strcmp(color, "chartreuse4") == 0) { - rgb->red = 69; - rgb->green = 139; - rgb->blue = 0; - return; - } - if(strcmp(color, "OliveDrab1") == 0) { - rgb->red = 192; - rgb->green = 255; - rgb->blue = 62; - return; - } - if(strcmp(color, "OliveDrab2") == 0) { - rgb->red = 179; - rgb->green = 238; - rgb->blue = 58; - return; - } - if(strcmp(color, "OliveDrab3") == 0) { - rgb->red = 154; - rgb->green = 205; - rgb->blue = 50; - return; - } - if(strcmp(color, "OliveDrab4") == 0) { - rgb->red = 105; - rgb->green = 139; - rgb->blue = 34; - return; - } - if(strcmp(color, "DarkOliveGreen1") == 0) { - rgb->red = 202; - rgb->green = 255; - rgb->blue = 112; - return; - } - if(strcmp(color, "DarkOliveGreen2") == 0) { - rgb->red = 188; - rgb->green = 238; - rgb->blue = 104; - return; - } - if(strcmp(color, "DarkOliveGreen3") == 0) { - rgb->red = 162; - rgb->green = 205; - rgb->blue = 90; - return; - } - if(strcmp(color, "DarkOliveGreen4") == 0) { - rgb->red = 110; - rgb->green = 139; - rgb->blue = 61; - return; - } - if(strcmp(color, "khaki1") == 0) { - rgb->red = 255; - rgb->green = 246; - rgb->blue = 143; - return; - } - if(strcmp(color, "khaki2") == 0) { - rgb->red = 238; - rgb->green = 230; - rgb->blue = 133; - return; - } - if(strcmp(color, "khaki3") == 0) { - rgb->red = 205; - rgb->green = 198; - rgb->blue = 115; - return; - } - if(strcmp(color, "khaki4") == 0) { - rgb->red = 139; - rgb->green = 134; - rgb->blue = 78; - return; - } - if(strcmp(color, "LightGoldenrod1") == 0) { - rgb->red = 255; - rgb->green = 236; - rgb->blue = 139; - return; - } - if(strcmp(color, "LightGoldenrod2") == 0) { - rgb->red = 238; - rgb->green = 220; - rgb->blue = 130; - return; - } - if(strcmp(color, "LightGoldenrod3") == 0) { - rgb->red = 205; - rgb->green = 190; - rgb->blue = 112; - return; - } - if(strcmp(color, "LightGoldenrod4") == 0) { - rgb->red = 139; - rgb->green = 129; - rgb->blue = 76; - return; - } - if(strcmp(color, "LightYellow1") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 224; - return; - } - if(strcmp(color, "LightYellow2") == 0) { - rgb->red = 238; - rgb->green = 238; - rgb->blue = 209; - return; - } - if(strcmp(color, "LightYellow3") == 0) { - rgb->red = 205; - rgb->green = 205; - rgb->blue = 180; - return; - } - if(strcmp(color, "LightYellow4") == 0) { - rgb->red = 139; - rgb->green = 139; - rgb->blue = 122; - return; - } - if(strcmp(color, "yellow1") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 0; - return; - } - if(strcmp(color, "yellow2") == 0) { - rgb->red = 238; - rgb->green = 238; - rgb->blue = 0; - return; - } - if(strcmp(color, "yellow3") == 0) { - rgb->red = 205; - rgb->green = 205; - rgb->blue = 0; - return; - } - if(strcmp(color, "yellow4") == 0) { - rgb->red = 139; - rgb->green = 139; - rgb->blue = 0; - return; - } - if(strcmp(color, "gold1") == 0) { - rgb->red = 255; - rgb->green = 215; - rgb->blue = 0; - return; - } - if(strcmp(color, "gold2") == 0) { - rgb->red = 238; - rgb->green = 201; - rgb->blue = 0; - return; - } - if(strcmp(color, "gold3") == 0) { - rgb->red = 205; - rgb->green = 173; - rgb->blue = 0; - return; - } - if(strcmp(color, "gold4") == 0) { - rgb->red = 139; - rgb->green = 117; - rgb->blue = 0; - return; - } - if(strcmp(color, "goldenrod1") == 0) { - rgb->red = 255; - rgb->green = 193; - rgb->blue = 37; - return; - } - if(strcmp(color, "goldenrod2") == 0) { - rgb->red = 238; - rgb->green = 180; - rgb->blue = 34; - return; - } - if(strcmp(color, "goldenrod3") == 0) { - rgb->red = 205; - rgb->green = 155; - rgb->blue = 29; - return; - } - if(strcmp(color, "goldenrod4") == 0) { - rgb->red = 139; - rgb->green = 105; - rgb->blue = 20; - return; - } - if(strcmp(color, "DarkGoldenrod1") == 0) { - rgb->red = 255; - rgb->green = 185; - rgb->blue = 15; - return; - } - if(strcmp(color, "DarkGoldenrod2") == 0) { - rgb->red = 238; - rgb->green = 173; - rgb->blue = 14; - return; - } - if(strcmp(color, "DarkGoldenrod3") == 0) { - rgb->red = 205; - rgb->green = 149; - rgb->blue = 12; - return; - } - if(strcmp(color, "DarkGoldenrod4") == 0) { - rgb->red = 139; - rgb->green = 101; - rgb->blue = 8; - return; - } - if(strcmp(color, "RosyBrown1") == 0) { - rgb->red = 255; - rgb->green = 193; - rgb->blue = 193; - return; - } - if(strcmp(color, "RosyBrown2") == 0) { - rgb->red = 238; - rgb->green = 180; - rgb->blue = 180; - return; - } - if(strcmp(color, "RosyBrown3") == 0) { - rgb->red = 205; - rgb->green = 155; - rgb->blue = 155; - return; - } - if(strcmp(color, "RosyBrown4") == 0) { - rgb->red = 139; - rgb->green = 105; - rgb->blue = 105; - return; - } - if(strcmp(color, "IndianRed1") == 0) { - rgb->red = 255; - rgb->green = 106; - rgb->blue = 106; - return; - } - if(strcmp(color, "IndianRed2") == 0) { - rgb->red = 238; - rgb->green = 99; - rgb->blue = 99; - return; - } - if(strcmp(color, "IndianRed3") == 0) { - rgb->red = 205; - rgb->green = 85; - rgb->blue = 85; - return; - } - if(strcmp(color, "IndianRed4") == 0) { - rgb->red = 139; - rgb->green = 58; - rgb->blue = 58; - return; - } - if(strcmp(color, "sienna1") == 0) { - rgb->red = 255; - rgb->green = 130; - rgb->blue = 71; - return; - } - if(strcmp(color, "sienna2") == 0) { - rgb->red = 238; - rgb->green = 121; - rgb->blue = 66; - return; - } - if(strcmp(color, "sienna3") == 0) { - rgb->red = 205; - rgb->green = 104; - rgb->blue = 57; - return; - } - if(strcmp(color, "sienna4") == 0) { - rgb->red = 139; - rgb->green = 71; - rgb->blue = 38; - return; - } - if(strcmp(color, "burlywood1") == 0) { - rgb->red = 255; - rgb->green = 211; - rgb->blue = 155; - return; - } - if(strcmp(color, "burlywood2") == 0) { - rgb->red = 238; - rgb->green = 197; - rgb->blue = 145; - return; - } - if(strcmp(color, "burlywood3") == 0) { - rgb->red = 205; - rgb->green = 170; - rgb->blue = 125; - return; - } - if(strcmp(color, "burlywood4") == 0) { - rgb->red = 139; - rgb->green = 115; - rgb->blue = 85; - return; - } - if(strcmp(color, "wheat1") == 0) { - rgb->red = 255; - rgb->green = 231; - rgb->blue = 186; - return; - } - if(strcmp(color, "wheat2") == 0) { - rgb->red = 238; - rgb->green = 216; - rgb->blue = 174; - return; - } - if(strcmp(color, "wheat3") == 0) { - rgb->red = 205; - rgb->green = 186; - rgb->blue = 150; - return; - } - if(strcmp(color, "wheat4") == 0) { - rgb->red = 139; - rgb->green = 126; - rgb->blue = 102; - return; - } - if(strcmp(color, "tan1") == 0) { - rgb->red = 255; - rgb->green = 165; - rgb->blue = 79; - return; - } - if(strcmp(color, "tan2") == 0) { - rgb->red = 238; - rgb->green = 154; - rgb->blue = 73; - return; - } - if(strcmp(color, "tan3") == 0) { - rgb->red = 205; - rgb->green = 133; - rgb->blue = 63; - return; - } - if(strcmp(color, "tan4") == 0) { - rgb->red = 139; - rgb->green = 90; - rgb->blue = 43; - return; - } - if(strcmp(color, "chocolate1") == 0) { - rgb->red = 255; - rgb->green = 127; - rgb->blue = 36; - return; - } - if(strcmp(color, "chocolate2") == 0) { - rgb->red = 238; - rgb->green = 118; - rgb->blue = 33; - return; - } - if(strcmp(color, "chocolate3") == 0) { - rgb->red = 205; - rgb->green = 102; - rgb->blue = 29; - return; - } - if(strcmp(color, "chocolate4") == 0) { - rgb->red = 139; - rgb->green = 69; - rgb->blue = 19; - return; - } - if(strcmp(color, "firebrick1") == 0) { - rgb->red = 255; - rgb->green = 48; - rgb->blue = 48; - return; - } - if(strcmp(color, "firebrick2") == 0) { - rgb->red = 238; - rgb->green = 44; - rgb->blue = 44; - return; - } - if(strcmp(color, "firebrick3") == 0) { - rgb->red = 205; - rgb->green = 38; - rgb->blue = 38; - return; - } - if(strcmp(color, "firebrick4") == 0) { - rgb->red = 139; - rgb->green = 26; - rgb->blue = 26; - return; - } - if(strcmp(color, "brown1") == 0) { - rgb->red = 255; - rgb->green = 64; - rgb->blue = 64; - return; - } - if(strcmp(color, "brown2") == 0) { - rgb->red = 238; - rgb->green = 59; - rgb->blue = 59; - return; - } - if(strcmp(color, "brown3") == 0) { - rgb->red = 205; - rgb->green = 51; - rgb->blue = 51; - return; - } - if(strcmp(color, "brown4") == 0) { - rgb->red = 139; - rgb->green = 35; - rgb->blue = 35; - return; - } - if(strcmp(color, "salmon1") == 0) { - rgb->red = 255; - rgb->green = 140; - rgb->blue = 105; - return; - } - if(strcmp(color, "salmon2") == 0) { - rgb->red = 238; - rgb->green = 130; - rgb->blue = 98; - return; - } - if(strcmp(color, "salmon3") == 0) { - rgb->red = 205; - rgb->green = 112; - rgb->blue = 84; - return; - } - if(strcmp(color, "salmon4") == 0) { - rgb->red = 139; - rgb->green = 76; - rgb->blue = 57; - return; - } - if(strcmp(color, "LightSalmon1") == 0) { - rgb->red = 255; - rgb->green = 160; - rgb->blue = 122; - return; - } - if(strcmp(color, "LightSalmon2") == 0) { - rgb->red = 238; - rgb->green = 149; - rgb->blue = 114; - return; - } - if(strcmp(color, "LightSalmon3") == 0) { - rgb->red = 205; - rgb->green = 129; - rgb->blue = 98; - return; - } - if(strcmp(color, "LightSalmon4") == 0) { - rgb->red = 139; - rgb->green = 87; - rgb->blue = 66; - return; - } - if(strcmp(color, "orange1") == 0) { - rgb->red = 255; - rgb->green = 165; - rgb->blue = 0; - return; - } - if(strcmp(color, "orange2") == 0) { - rgb->red = 238; - rgb->green = 154; - rgb->blue = 0; - return; - } - if(strcmp(color, "orange3") == 0) { - rgb->red = 205; - rgb->green = 133; - rgb->blue = 0; - return; - } - if(strcmp(color, "orange4") == 0) { - rgb->red = 139; - rgb->green = 90; - rgb->blue = 0; - return; - } - if(strcmp(color, "DarkOrange1") == 0) { - rgb->red = 255; - rgb->green = 127; - rgb->blue = 0; - return; - } - if(strcmp(color, "DarkOrange2") == 0) { - rgb->red = 238; - rgb->green = 118; - rgb->blue = 0; - return; - } - if(strcmp(color, "DarkOrange3") == 0) { - rgb->red = 205; - rgb->green = 102; - rgb->blue = 0; - return; - } - if(strcmp(color, "DarkOrange4") == 0) { - rgb->red = 139; - rgb->green = 69; - rgb->blue = 0; - return; - } - if(strcmp(color, "coral1") == 0) { - rgb->red = 255; - rgb->green = 114; - rgb->blue = 86; - return; - } - if(strcmp(color, "coral2") == 0) { - rgb->red = 238; - rgb->green = 106; - rgb->blue = 80; - return; - } - if(strcmp(color, "coral3") == 0) { - rgb->red = 205; - rgb->green = 91; - rgb->blue = 69; - return; - } - if(strcmp(color, "coral4") == 0) { - rgb->red = 139; - rgb->green = 62; - rgb->blue = 47; - return; - } - if(strcmp(color, "tomato1") == 0) { - rgb->red = 255; - rgb->green = 99; - rgb->blue = 71; - return; - } - if(strcmp(color, "tomato2") == 0) { - rgb->red = 238; - rgb->green = 92; - rgb->blue = 66; - return; - } - if(strcmp(color, "tomato3") == 0) { - rgb->red = 205; - rgb->green = 79; - rgb->blue = 57; - return; - } - if(strcmp(color, "tomato4") == 0) { - rgb->red = 139; - rgb->green = 54; - rgb->blue = 38; - return; - } - if(strcmp(color, "OrangeRed1") == 0) { - rgb->red = 255; - rgb->green = 69; - rgb->blue = 0; - return; - } - if(strcmp(color, "OrangeRed2") == 0) { - rgb->red = 238; - rgb->green = 64; - rgb->blue = 0; - return; - } - if(strcmp(color, "OrangeRed3") == 0) { - rgb->red = 205; - rgb->green = 55; - rgb->blue = 0; - return; - } - if(strcmp(color, "OrangeRed4") == 0) { - rgb->red = 139; - rgb->green = 37; - rgb->blue = 0; - return; - } - if(strcmp(color, "red1") == 0) { - rgb->red = 255; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "red2") == 0) { - rgb->red = 238; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "red3") == 0) { - rgb->red = 205; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "red4") == 0) { - rgb->red = 139; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "DeepPink1") == 0) { - rgb->red = 255; - rgb->green = 20; - rgb->blue = 147; - return; - } - if(strcmp(color, "DeepPink2") == 0) { - rgb->red = 238; - rgb->green = 18; - rgb->blue = 137; - return; - } - if(strcmp(color, "DeepPink3") == 0) { - rgb->red = 205; - rgb->green = 16; - rgb->blue = 118; - return; - } - if(strcmp(color, "DeepPink4") == 0) { - rgb->red = 139; - rgb->green = 10; - rgb->blue = 80; - return; - } - if(strcmp(color, "HotPink1") == 0) { - rgb->red = 255; - rgb->green = 110; - rgb->blue = 180; - return; - } - if(strcmp(color, "HotPink2") == 0) { - rgb->red = 238; - rgb->green = 106; - rgb->blue = 167; - return; - } - if(strcmp(color, "HotPink3") == 0) { - rgb->red = 205; - rgb->green = 96; - rgb->blue = 144; - return; - } - if(strcmp(color, "HotPink4") == 0) { - rgb->red = 139; - rgb->green = 58; - rgb->blue = 98; - return; - } - if(strcmp(color, "pink1") == 0) { - rgb->red = 255; - rgb->green = 181; - rgb->blue = 197; - return; - } - if(strcmp(color, "pink2") == 0) { - rgb->red = 238; - rgb->green = 169; - rgb->blue = 184; - return; - } - if(strcmp(color, "pink3") == 0) { - rgb->red = 205; - rgb->green = 145; - rgb->blue = 158; - return; - } - if(strcmp(color, "pink4") == 0) { - rgb->red = 139; - rgb->green = 99; - rgb->blue = 108; - return; - } - if(strcmp(color, "LightPink1") == 0) { - rgb->red = 255; - rgb->green = 174; - rgb->blue = 185; - return; - } - if(strcmp(color, "LightPink2") == 0) { - rgb->red = 238; - rgb->green = 162; - rgb->blue = 173; - return; - } - if(strcmp(color, "LightPink3") == 0) { - rgb->red = 205; - rgb->green = 140; - rgb->blue = 149; - return; - } - if(strcmp(color, "LightPink4") == 0) { - rgb->red = 139; - rgb->green = 95; - rgb->blue = 101; - return; - } - if(strcmp(color, "PaleVioletRed1") == 0) { - rgb->red = 255; - rgb->green = 130; - rgb->blue = 171; - return; - } - if(strcmp(color, "PaleVioletRed2") == 0) { - rgb->red = 238; - rgb->green = 121; - rgb->blue = 159; - return; - } - if(strcmp(color, "PaleVioletRed3") == 0) { - rgb->red = 205; - rgb->green = 104; - rgb->blue = 137; - return; - } - if(strcmp(color, "PaleVioletRed4") == 0) { - rgb->red = 139; - rgb->green = 71; - rgb->blue = 93; - return; - } - if(strcmp(color, "maroon1") == 0) { - rgb->red = 255; - rgb->green = 52; - rgb->blue = 179; - return; - } - if(strcmp(color, "maroon2") == 0) { - rgb->red = 238; - rgb->green = 48; - rgb->blue = 167; - return; - } - if(strcmp(color, "maroon3") == 0) { - rgb->red = 205; - rgb->green = 41; - rgb->blue = 144; - return; - } - if(strcmp(color, "maroon4") == 0) { - rgb->red = 139; - rgb->green = 28; - rgb->blue = 98; - return; - } - if(strcmp(color, "VioletRed1") == 0) { - rgb->red = 255; - rgb->green = 62; - rgb->blue = 150; - return; - } - if(strcmp(color, "VioletRed2") == 0) { - rgb->red = 238; - rgb->green = 58; - rgb->blue = 140; - return; - } - if(strcmp(color, "VioletRed3") == 0) { - rgb->red = 205; - rgb->green = 50; - rgb->blue = 120; - return; - } - if(strcmp(color, "VioletRed4") == 0) { - rgb->red = 139; - rgb->green = 34; - rgb->blue = 82; - return; - } - if(strcmp(color, "magenta1") == 0) { - rgb->red = 255; - rgb->green = 0; - rgb->blue = 255; - return; - } - if(strcmp(color, "magenta2") == 0) { - rgb->red = 238; - rgb->green = 0; - rgb->blue = 238; - return; - } - if(strcmp(color, "magenta3") == 0) { - rgb->red = 205; - rgb->green = 0; - rgb->blue = 205; - return; - } - if(strcmp(color, "magenta4") == 0) { - rgb->red = 139; - rgb->green = 0; - rgb->blue = 139; - return; - } - if(strcmp(color, "orchid1") == 0) { - rgb->red = 255; - rgb->green = 131; - rgb->blue = 250; - return; - } - if(strcmp(color, "orchid2") == 0) { - rgb->red = 238; - rgb->green = 122; - rgb->blue = 233; - return; - } - if(strcmp(color, "orchid3") == 0) { - rgb->red = 205; - rgb->green = 105; - rgb->blue = 201; - return; - } - if(strcmp(color, "orchid4") == 0) { - rgb->red = 139; - rgb->green = 71; - rgb->blue = 137; - return; - } - if(strcmp(color, "plum1") == 0) { - rgb->red = 255; - rgb->green = 187; - rgb->blue = 255; - return; - } - if(strcmp(color, "plum2") == 0) { - rgb->red = 238; - rgb->green = 174; - rgb->blue = 238; - return; - } - if(strcmp(color, "plum3") == 0) { - rgb->red = 205; - rgb->green = 150; - rgb->blue = 205; - return; - } - if(strcmp(color, "plum4") == 0) { - rgb->red = 139; - rgb->green = 102; - rgb->blue = 139; - return; - } - if(strcmp(color, "MediumOrchid1") == 0) { - rgb->red = 224; - rgb->green = 102; - rgb->blue = 255; - return; - } - if(strcmp(color, "MediumOrchid2") == 0) { - rgb->red = 209; - rgb->green = 95; - rgb->blue = 238; - return; - } - if(strcmp(color, "MediumOrchid3") == 0) { - rgb->red = 180; - rgb->green = 82; - rgb->blue = 205; - return; - } - if(strcmp(color, "MediumOrchid4") == 0) { - rgb->red = 122; - rgb->green = 55; - rgb->blue = 139; - return; - } - if(strcmp(color, "DarkOrchid1") == 0) { - rgb->red = 191; - rgb->green = 62; - rgb->blue = 255; - return; - } - if(strcmp(color, "DarkOrchid2") == 0) { - rgb->red = 178; - rgb->green = 58; - rgb->blue = 238; - return; - } - if(strcmp(color, "DarkOrchid3") == 0) { - rgb->red = 154; - rgb->green = 50; - rgb->blue = 205; - return; - } - if(strcmp(color, "DarkOrchid4") == 0) { - rgb->red = 104; - rgb->green = 34; - rgb->blue = 139; - return; - } - if(strcmp(color, "purple1") == 0) { - rgb->red = 155; - rgb->green = 48; - rgb->blue = 255; - return; - } - if(strcmp(color, "purple2") == 0) { - rgb->red = 145; - rgb->green = 44; - rgb->blue = 238; - return; - } - if(strcmp(color, "purple3") == 0) { - rgb->red = 125; - rgb->green = 38; - rgb->blue = 205; - return; - } - if(strcmp(color, "purple4") == 0) { - rgb->red = 85; - rgb->green = 26; - rgb->blue = 139; - return; - } - if(strcmp(color, "MediumPurple1") == 0) { - rgb->red = 171; - rgb->green = 130; - rgb->blue = 255; - return; - } - if(strcmp(color, "MediumPurple2") == 0) { - rgb->red = 159; - rgb->green = 121; - rgb->blue = 238; - return; - } - if(strcmp(color, "MediumPurple3") == 0) { - rgb->red = 137; - rgb->green = 104; - rgb->blue = 205; - return; - } - if(strcmp(color, "MediumPurple4") == 0) { - rgb->red = 93; - rgb->green = 71; - rgb->blue = 139; - return; - } - if(strcmp(color, "thistle1") == 0) { - rgb->red = 255; - rgb->green = 225; - rgb->blue = 255; - return; - } - if(strcmp(color, "thistle2") == 0) { - rgb->red = 238; - rgb->green = 210; - rgb->blue = 238; - return; - } - if(strcmp(color, "thistle3") == 0) { - rgb->red = 205; - rgb->green = 181; - rgb->blue = 205; - return; - } - if(strcmp(color, "thistle4") == 0) { - rgb->red = 139; - rgb->green = 123; - rgb->blue = 139; - return; - } - if(strcmp(color, "gray0") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "grey0") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "gray1") == 0) { - rgb->red = 3; - rgb->green = 3; - rgb->blue = 3; - return; - } - if(strcmp(color, "grey1") == 0) { - rgb->red = 3; - rgb->green = 3; - rgb->blue = 3; - return; - } - if(strcmp(color, "gray2") == 0) { - rgb->red = 5; - rgb->green = 5; - rgb->blue = 5; - return; - } - if(strcmp(color, "grey2") == 0) { - rgb->red = 5; - rgb->green = 5; - rgb->blue = 5; - return; - } - if(strcmp(color, "gray3") == 0) { - rgb->red = 8; - rgb->green = 8; - rgb->blue = 8; - return; - } - if(strcmp(color, "grey3") == 0) { - rgb->red = 8; - rgb->green = 8; - rgb->blue = 8; - return; - } - if(strcmp(color, "gray4") == 0) { - rgb->red = 10; - rgb->green = 10; - rgb->blue = 10; - return; - } - if(strcmp(color, "grey4") == 0) { - rgb->red = 10; - rgb->green = 10; - rgb->blue = 10; - return; - } - if(strcmp(color, "gray5") == 0) { - rgb->red = 13; - rgb->green = 13; - rgb->blue = 13; - return; - } - if(strcmp(color, "grey5") == 0) { - rgb->red = 13; - rgb->green = 13; - rgb->blue = 13; - return; - } - if(strcmp(color, "gray6") == 0) { - rgb->red = 15; - rgb->green = 15; - rgb->blue = 15; - return; - } - if(strcmp(color, "grey6") == 0) { - rgb->red = 15; - rgb->green = 15; - rgb->blue = 15; - return; - } - if(strcmp(color, "gray7") == 0) { - rgb->red = 18; - rgb->green = 18; - rgb->blue = 18; - return; - } - if(strcmp(color, "grey7") == 0) { - rgb->red = 18; - rgb->green = 18; - rgb->blue = 18; - return; - } - if(strcmp(color, "gray8") == 0) { - rgb->red = 20; - rgb->green = 20; - rgb->blue = 20; - return; - } - if(strcmp(color, "grey8") == 0) { - rgb->red = 20; - rgb->green = 20; - rgb->blue = 20; - return; - } - if(strcmp(color, "gray9") == 0) { - rgb->red = 23; - rgb->green = 23; - rgb->blue = 23; - return; - } - if(strcmp(color, "grey9") == 0) { - rgb->red = 23; - rgb->green = 23; - rgb->blue = 23; - return; - } - if(strcmp(color, "gray10") == 0) { - rgb->red = 26; - rgb->green = 26; - rgb->blue = 26; - return; - } - if(strcmp(color, "grey10") == 0) { - rgb->red = 26; - rgb->green = 26; - rgb->blue = 26; - return; - } - if(strcmp(color, "gray11") == 0) { - rgb->red = 28; - rgb->green = 28; - rgb->blue = 28; - return; - } - if(strcmp(color, "grey11") == 0) { - rgb->red = 28; - rgb->green = 28; - rgb->blue = 28; - return; - } - if(strcmp(color, "gray12") == 0) { - rgb->red = 31; - rgb->green = 31; - rgb->blue = 31; - return; - } - if(strcmp(color, "grey12") == 0) { - rgb->red = 31; - rgb->green = 31; - rgb->blue = 31; - return; - } - if(strcmp(color, "gray13") == 0) { - rgb->red = 33; - rgb->green = 33; - rgb->blue = 33; - return; - } - if(strcmp(color, "grey13") == 0) { - rgb->red = 33; - rgb->green = 33; - rgb->blue = 33; - return; - } - if(strcmp(color, "gray14") == 0) { - rgb->red = 36; - rgb->green = 36; - rgb->blue = 36; - return; - } - if(strcmp(color, "grey14") == 0) { - rgb->red = 36; - rgb->green = 36; - rgb->blue = 36; - return; - } - if(strcmp(color, "gray15") == 0) { - rgb->red = 38; - rgb->green = 38; - rgb->blue = 38; - return; - } - if(strcmp(color, "grey15") == 0) { - rgb->red = 38; - rgb->green = 38; - rgb->blue = 38; - return; - } - if(strcmp(color, "gray16") == 0) { - rgb->red = 41; - rgb->green = 41; - rgb->blue = 41; - return; - } - if(strcmp(color, "grey16") == 0) { - rgb->red = 41; - rgb->green = 41; - rgb->blue = 41; - return; - } - if(strcmp(color, "gray17") == 0) { - rgb->red = 43; - rgb->green = 43; - rgb->blue = 43; - return; - } - if(strcmp(color, "grey17") == 0) { - rgb->red = 43; - rgb->green = 43; - rgb->blue = 43; - return; - } - if(strcmp(color, "gray18") == 0) { - rgb->red = 46; - rgb->green = 46; - rgb->blue = 46; - return; - } - if(strcmp(color, "grey18") == 0) { - rgb->red = 46; - rgb->green = 46; - rgb->blue = 46; - return; - } - if(strcmp(color, "gray19") == 0) { - rgb->red = 48; - rgb->green = 48; - rgb->blue = 48; - return; - } - if(strcmp(color, "grey19") == 0) { - rgb->red = 48; - rgb->green = 48; - rgb->blue = 48; - return; - } - if(strcmp(color, "gray20") == 0) { - rgb->red = 51; - rgb->green = 51; - rgb->blue = 51; - return; - } - if(strcmp(color, "grey20") == 0) { - rgb->red = 51; - rgb->green = 51; - rgb->blue = 51; - return; - } - if(strcmp(color, "gray21") == 0) { - rgb->red = 54; - rgb->green = 54; - rgb->blue = 54; - return; - } - if(strcmp(color, "grey21") == 0) { - rgb->red = 54; - rgb->green = 54; - rgb->blue = 54; - return; - } - if(strcmp(color, "gray22") == 0) { - rgb->red = 56; - rgb->green = 56; - rgb->blue = 56; - return; - } - if(strcmp(color, "grey22") == 0) { - rgb->red = 56; - rgb->green = 56; - rgb->blue = 56; - return; - } - if(strcmp(color, "gray23") == 0) { - rgb->red = 59; - rgb->green = 59; - rgb->blue = 59; - return; - } - if(strcmp(color, "grey23") == 0) { - rgb->red = 59; - rgb->green = 59; - rgb->blue = 59; - return; - } - if(strcmp(color, "gray24") == 0) { - rgb->red = 61; - rgb->green = 61; - rgb->blue = 61; - return; - } - if(strcmp(color, "grey24") == 0) { - rgb->red = 61; - rgb->green = 61; - rgb->blue = 61; - return; - } - if(strcmp(color, "gray25") == 0) { - rgb->red = 64; - rgb->green = 64; - rgb->blue = 64; - return; - } - if(strcmp(color, "grey25") == 0) { - rgb->red = 64; - rgb->green = 64; - rgb->blue = 64; - return; - } - if(strcmp(color, "gray26") == 0) { - rgb->red = 66; - rgb->green = 66; - rgb->blue = 66; - return; - } - if(strcmp(color, "grey26") == 0) { - rgb->red = 66; - rgb->green = 66; - rgb->blue = 66; - return; - } - if(strcmp(color, "gray27") == 0) { - rgb->red = 69; - rgb->green = 69; - rgb->blue = 69; - return; - } - if(strcmp(color, "grey27") == 0) { - rgb->red = 69; - rgb->green = 69; - rgb->blue = 69; - return; - } - if(strcmp(color, "gray28") == 0) { - rgb->red = 71; - rgb->green = 71; - rgb->blue = 71; - return; - } - if(strcmp(color, "grey28") == 0) { - rgb->red = 71; - rgb->green = 71; - rgb->blue = 71; - return; - } - if(strcmp(color, "gray29") == 0) { - rgb->red = 74; - rgb->green = 74; - rgb->blue = 74; - return; - } - if(strcmp(color, "grey29") == 0) { - rgb->red = 74; - rgb->green = 74; - rgb->blue = 74; - return; - } - if(strcmp(color, "gray30") == 0) { - rgb->red = 77; - rgb->green = 77; - rgb->blue = 77; - return; - } - if(strcmp(color, "grey30") == 0) { - rgb->red = 77; - rgb->green = 77; - rgb->blue = 77; - return; - } - if(strcmp(color, "gray31") == 0) { - rgb->red = 79; - rgb->green = 79; - rgb->blue = 79; - return; - } - if(strcmp(color, "grey31") == 0) { - rgb->red = 79; - rgb->green = 79; - rgb->blue = 79; - return; - } - if(strcmp(color, "gray32") == 0) { - rgb->red = 82; - rgb->green = 82; - rgb->blue = 82; - return; - } - if(strcmp(color, "grey32") == 0) { - rgb->red = 82; - rgb->green = 82; - rgb->blue = 82; - return; - } - if(strcmp(color, "gray33") == 0) { - rgb->red = 84; - rgb->green = 84; - rgb->blue = 84; - return; - } - if(strcmp(color, "grey33") == 0) { - rgb->red = 84; - rgb->green = 84; - rgb->blue = 84; - return; - } - if(strcmp(color, "gray34") == 0) { - rgb->red = 87; - rgb->green = 87; - rgb->blue = 87; - return; - } - if(strcmp(color, "grey34") == 0) { - rgb->red = 87; - rgb->green = 87; - rgb->blue = 87; - return; - } - if(strcmp(color, "gray35") == 0) { - rgb->red = 89; - rgb->green = 89; - rgb->blue = 89; - return; - } - if(strcmp(color, "grey35") == 0) { - rgb->red = 89; - rgb->green = 89; - rgb->blue = 89; - return; - } - if(strcmp(color, "gray36") == 0) { - rgb->red = 92; - rgb->green = 92; - rgb->blue = 92; - return; - } - if(strcmp(color, "grey36") == 0) { - rgb->red = 92; - rgb->green = 92; - rgb->blue = 92; - return; - } - if(strcmp(color, "gray37") == 0) { - rgb->red = 94; - rgb->green = 94; - rgb->blue = 94; - return; - } - if(strcmp(color, "grey37") == 0) { - rgb->red = 94; - rgb->green = 94; - rgb->blue = 94; - return; - } - if(strcmp(color, "gray38") == 0) { - rgb->red = 97; - rgb->green = 97; - rgb->blue = 97; - return; - } - if(strcmp(color, "grey38") == 0) { - rgb->red = 97; - rgb->green = 97; - rgb->blue = 97; - return; - } - if(strcmp(color, "gray39") == 0) { - rgb->red = 99; - rgb->green = 99; - rgb->blue = 99; - return; - } - if(strcmp(color, "grey39") == 0) { - rgb->red = 99; - rgb->green = 99; - rgb->blue = 99; - return; - } - if(strcmp(color, "gray40") == 0) { - rgb->red = 102; - rgb->green = 102; - rgb->blue = 102; - return; - } - if(strcmp(color, "grey40") == 0) { - rgb->red = 102; - rgb->green = 102; - rgb->blue = 102; - return; - } - if(strcmp(color, "gray41") == 0) { - rgb->red = 105; - rgb->green = 105; - rgb->blue = 105; - return; - } - if(strcmp(color, "grey41") == 0) { - rgb->red = 105; - rgb->green = 105; - rgb->blue = 105; - return; - } - if(strcmp(color, "gray42") == 0) { - rgb->red = 107; - rgb->green = 107; - rgb->blue = 107; - return; - } - if(strcmp(color, "grey42") == 0) { - rgb->red = 107; - rgb->green = 107; - rgb->blue = 107; - return; - } - if(strcmp(color, "gray43") == 0) { - rgb->red = 110; - rgb->green = 110; - rgb->blue = 110; - return; - } - if(strcmp(color, "grey43") == 0) { - rgb->red = 110; - rgb->green = 110; - rgb->blue = 110; - return; - } - if(strcmp(color, "gray44") == 0) { - rgb->red = 112; - rgb->green = 112; - rgb->blue = 112; - return; - } - if(strcmp(color, "grey44") == 0) { - rgb->red = 112; - rgb->green = 112; - rgb->blue = 112; - return; - } - if(strcmp(color, "gray45") == 0) { - rgb->red = 115; - rgb->green = 115; - rgb->blue = 115; - return; - } - if(strcmp(color, "grey45") == 0) { - rgb->red = 115; - rgb->green = 115; - rgb->blue = 115; - return; - } - if(strcmp(color, "gray46") == 0) { - rgb->red = 117; - rgb->green = 117; - rgb->blue = 117; - return; - } - if(strcmp(color, "grey46") == 0) { - rgb->red = 117; - rgb->green = 117; - rgb->blue = 117; - return; - } - if(strcmp(color, "gray47") == 0) { - rgb->red = 120; - rgb->green = 120; - rgb->blue = 120; - return; - } - if(strcmp(color, "grey47") == 0) { - rgb->red = 120; - rgb->green = 120; - rgb->blue = 120; - return; - } - if(strcmp(color, "gray48") == 0) { - rgb->red = 122; - rgb->green = 122; - rgb->blue = 122; - return; - } - if(strcmp(color, "grey48") == 0) { - rgb->red = 122; - rgb->green = 122; - rgb->blue = 122; - return; - } - if(strcmp(color, "gray49") == 0) { - rgb->red = 125; - rgb->green = 125; - rgb->blue = 125; - return; - } - if(strcmp(color, "grey49") == 0) { - rgb->red = 125; - rgb->green = 125; - rgb->blue = 125; - return; - } - if(strcmp(color, "gray50") == 0) { - rgb->red = 127; - rgb->green = 127; - rgb->blue = 127; - return; - } - if(strcmp(color, "grey50") == 0) { - rgb->red = 127; - rgb->green = 127; - rgb->blue = 127; - return; - } - if(strcmp(color, "gray51") == 0) { - rgb->red = 130; - rgb->green = 130; - rgb->blue = 130; - return; - } - if(strcmp(color, "grey51") == 0) { - rgb->red = 130; - rgb->green = 130; - rgb->blue = 130; - return; - } - if(strcmp(color, "gray52") == 0) { - rgb->red = 133; - rgb->green = 133; - rgb->blue = 133; - return; - } - if(strcmp(color, "grey52") == 0) { - rgb->red = 133; - rgb->green = 133; - rgb->blue = 133; - return; - } - if(strcmp(color, "gray53") == 0) { - rgb->red = 135; - rgb->green = 135; - rgb->blue = 135; - return; - } - if(strcmp(color, "grey53") == 0) { - rgb->red = 135; - rgb->green = 135; - rgb->blue = 135; - return; - } - if(strcmp(color, "gray54") == 0) { - rgb->red = 138; - rgb->green = 138; - rgb->blue = 138; - return; - } - if(strcmp(color, "grey54") == 0) { - rgb->red = 138; - rgb->green = 138; - rgb->blue = 138; - return; - } - if(strcmp(color, "gray55") == 0) { - rgb->red = 140; - rgb->green = 140; - rgb->blue = 140; - return; - } - if(strcmp(color, "grey55") == 0) { - rgb->red = 140; - rgb->green = 140; - rgb->blue = 140; - return; - } - if(strcmp(color, "gray56") == 0) { - rgb->red = 143; - rgb->green = 143; - rgb->blue = 143; - return; - } - if(strcmp(color, "grey56") == 0) { - rgb->red = 143; - rgb->green = 143; - rgb->blue = 143; - return; - } - if(strcmp(color, "gray57") == 0) { - rgb->red = 145; - rgb->green = 145; - rgb->blue = 145; - return; - } - if(strcmp(color, "grey57") == 0) { - rgb->red = 145; - rgb->green = 145; - rgb->blue = 145; - return; - } - if(strcmp(color, "gray58") == 0) { - rgb->red = 148; - rgb->green = 148; - rgb->blue = 148; - return; - } - if(strcmp(color, "grey58") == 0) { - rgb->red = 148; - rgb->green = 148; - rgb->blue = 148; - return; - } - if(strcmp(color, "gray59") == 0) { - rgb->red = 150; - rgb->green = 150; - rgb->blue = 150; - return; - } - if(strcmp(color, "grey59") == 0) { - rgb->red = 150; - rgb->green = 150; - rgb->blue = 150; - return; - } - if(strcmp(color, "gray60") == 0) { - rgb->red = 153; - rgb->green = 153; - rgb->blue = 153; - return; - } - if(strcmp(color, "grey60") == 0) { - rgb->red = 153; - rgb->green = 153; - rgb->blue = 153; - return; - } - if(strcmp(color, "gray61") == 0) { - rgb->red = 156; - rgb->green = 156; - rgb->blue = 156; - return; - } - if(strcmp(color, "grey61") == 0) { - rgb->red = 156; - rgb->green = 156; - rgb->blue = 156; - return; - } - if(strcmp(color, "gray62") == 0) { - rgb->red = 158; - rgb->green = 158; - rgb->blue = 158; - return; - } - if(strcmp(color, "grey62") == 0) { - rgb->red = 158; - rgb->green = 158; - rgb->blue = 158; - return; - } - if(strcmp(color, "gray63") == 0) { - rgb->red = 161; - rgb->green = 161; - rgb->blue = 161; - return; - } - if(strcmp(color, "grey63") == 0) { - rgb->red = 161; - rgb->green = 161; - rgb->blue = 161; - return; - } - if(strcmp(color, "gray64") == 0) { - rgb->red = 163; - rgb->green = 163; - rgb->blue = 163; - return; - } - if(strcmp(color, "grey64") == 0) { - rgb->red = 163; - rgb->green = 163; - rgb->blue = 163; - return; - } - if(strcmp(color, "gray65") == 0) { - rgb->red = 166; - rgb->green = 166; - rgb->blue = 166; - return; - } - if(strcmp(color, "grey65") == 0) { - rgb->red = 166; - rgb->green = 166; - rgb->blue = 166; - return; - } - if(strcmp(color, "gray66") == 0) { - rgb->red = 168; - rgb->green = 168; - rgb->blue = 168; - return; - } - if(strcmp(color, "grey66") == 0) { - rgb->red = 168; - rgb->green = 168; - rgb->blue = 168; - return; - } - if(strcmp(color, "gray67") == 0) { - rgb->red = 171; - rgb->green = 171; - rgb->blue = 171; - return; - } - if(strcmp(color, "grey67") == 0) { - rgb->red = 171; - rgb->green = 171; - rgb->blue = 171; - return; - } - if(strcmp(color, "gray68") == 0) { - rgb->red = 173; - rgb->green = 173; - rgb->blue = 173; - return; - } - if(strcmp(color, "grey68") == 0) { - rgb->red = 173; - rgb->green = 173; - rgb->blue = 173; - return; - } - if(strcmp(color, "gray69") == 0) { - rgb->red = 176; - rgb->green = 176; - rgb->blue = 176; - return; - } - if(strcmp(color, "grey69") == 0) { - rgb->red = 176; - rgb->green = 176; - rgb->blue = 176; - return; - } - if(strcmp(color, "gray70") == 0) { - rgb->red = 179; - rgb->green = 179; - rgb->blue = 179; - return; - } - if(strcmp(color, "grey70") == 0) { - rgb->red = 179; - rgb->green = 179; - rgb->blue = 179; - return; - } - if(strcmp(color, "gray71") == 0) { - rgb->red = 181; - rgb->green = 181; - rgb->blue = 181; - return; - } - if(strcmp(color, "grey71") == 0) { - rgb->red = 181; - rgb->green = 181; - rgb->blue = 181; - return; - } - if(strcmp(color, "gray72") == 0) { - rgb->red = 184; - rgb->green = 184; - rgb->blue = 184; - return; - } - if(strcmp(color, "grey72") == 0) { - rgb->red = 184; - rgb->green = 184; - rgb->blue = 184; - return; - } - if(strcmp(color, "gray73") == 0) { - rgb->red = 186; - rgb->green = 186; - rgb->blue = 186; - return; - } - if(strcmp(color, "grey73") == 0) { - rgb->red = 186; - rgb->green = 186; - rgb->blue = 186; - return; - } - if(strcmp(color, "gray74") == 0) { - rgb->red = 189; - rgb->green = 189; - rgb->blue = 189; - return; - } - if(strcmp(color, "grey74") == 0) { - rgb->red = 189; - rgb->green = 189; - rgb->blue = 189; - return; - } - if(strcmp(color, "gray75") == 0) { - rgb->red = 191; - rgb->green = 191; - rgb->blue = 191; - return; - } - if(strcmp(color, "grey75") == 0) { - rgb->red = 191; - rgb->green = 191; - rgb->blue = 191; - return; - } - if(strcmp(color, "gray76") == 0) { - rgb->red = 194; - rgb->green = 194; - rgb->blue = 194; - return; - } - if(strcmp(color, "grey76") == 0) { - rgb->red = 194; - rgb->green = 194; - rgb->blue = 194; - return; - } - if(strcmp(color, "gray77") == 0) { - rgb->red = 196; - rgb->green = 196; - rgb->blue = 196; - return; - } - if(strcmp(color, "grey77") == 0) { - rgb->red = 196; - rgb->green = 196; - rgb->blue = 196; - return; - } - if(strcmp(color, "gray78") == 0) { - rgb->red = 199; - rgb->green = 199; - rgb->blue = 199; - return; - } - if(strcmp(color, "grey78") == 0) { - rgb->red = 199; - rgb->green = 199; - rgb->blue = 199; - return; - } - if(strcmp(color, "gray79") == 0) { - rgb->red = 201; - rgb->green = 201; - rgb->blue = 201; - return; - } - if(strcmp(color, "grey79") == 0) { - rgb->red = 201; - rgb->green = 201; - rgb->blue = 201; - return; - } - if(strcmp(color, "gray80") == 0) { - rgb->red = 204; - rgb->green = 204; - rgb->blue = 204; - return; - } - if(strcmp(color, "grey80") == 0) { - rgb->red = 204; - rgb->green = 204; - rgb->blue = 204; - return; - } - if(strcmp(color, "gray81") == 0) { - rgb->red = 207; - rgb->green = 207; - rgb->blue = 207; - return; - } - if(strcmp(color, "grey81") == 0) { - rgb->red = 207; - rgb->green = 207; - rgb->blue = 207; - return; - } - if(strcmp(color, "gray82") == 0) { - rgb->red = 209; - rgb->green = 209; - rgb->blue = 209; - return; - } - if(strcmp(color, "grey82") == 0) { - rgb->red = 209; - rgb->green = 209; - rgb->blue = 209; - return; - } - if(strcmp(color, "gray83") == 0) { - rgb->red = 212; - rgb->green = 212; - rgb->blue = 212; - return; - } - if(strcmp(color, "grey83") == 0) { - rgb->red = 212; - rgb->green = 212; - rgb->blue = 212; - return; - } - if(strcmp(color, "gray84") == 0) { - rgb->red = 214; - rgb->green = 214; - rgb->blue = 214; - return; - } - if(strcmp(color, "grey84") == 0) { - rgb->red = 214; - rgb->green = 214; - rgb->blue = 214; - return; - } - if(strcmp(color, "gray85") == 0) { - rgb->red = 217; - rgb->green = 217; - rgb->blue = 217; - return; - } - if(strcmp(color, "grey85") == 0) { - rgb->red = 217; - rgb->green = 217; - rgb->blue = 217; - return; - } - if(strcmp(color, "gray86") == 0) { - rgb->red = 219; - rgb->green = 219; - rgb->blue = 219; - return; - } - if(strcmp(color, "grey86") == 0) { - rgb->red = 219; - rgb->green = 219; - rgb->blue = 219; - return; - } - if(strcmp(color, "gray87") == 0) { - rgb->red = 222; - rgb->green = 222; - rgb->blue = 222; - return; - } - if(strcmp(color, "grey87") == 0) { - rgb->red = 222; - rgb->green = 222; - rgb->blue = 222; - return; - } - if(strcmp(color, "gray88") == 0) { - rgb->red = 224; - rgb->green = 224; - rgb->blue = 224; - return; - } - if(strcmp(color, "grey88") == 0) { - rgb->red = 224; - rgb->green = 224; - rgb->blue = 224; - return; - } - if(strcmp(color, "gray89") == 0) { - rgb->red = 227; - rgb->green = 227; - rgb->blue = 227; - return; - } - if(strcmp(color, "grey89") == 0) { - rgb->red = 227; - rgb->green = 227; - rgb->blue = 227; - return; - } - if(strcmp(color, "gray90") == 0) { - rgb->red = 229; - rgb->green = 229; - rgb->blue = 229; - return; - } - if(strcmp(color, "grey90") == 0) { - rgb->red = 229; - rgb->green = 229; - rgb->blue = 229; - return; - } - if(strcmp(color, "gray91") == 0) { - rgb->red = 232; - rgb->green = 232; - rgb->blue = 232; - return; - } - if(strcmp(color, "grey91") == 0) { - rgb->red = 232; - rgb->green = 232; - rgb->blue = 232; - return; - } - if(strcmp(color, "gray92") == 0) { - rgb->red = 235; - rgb->green = 235; - rgb->blue = 235; - return; - } - if(strcmp(color, "grey92") == 0) { - rgb->red = 235; - rgb->green = 235; - rgb->blue = 235; - return; - } - if(strcmp(color, "gray93") == 0) { - rgb->red = 237; - rgb->green = 237; - rgb->blue = 237; - return; - } - if(strcmp(color, "grey93") == 0) { - rgb->red = 237; - rgb->green = 237; - rgb->blue = 237; - return; - } - if(strcmp(color, "gray94") == 0) { - rgb->red = 240; - rgb->green = 240; - rgb->blue = 240; - return; - } - if(strcmp(color, "grey94") == 0) { - rgb->red = 240; - rgb->green = 240; - rgb->blue = 240; - return; - } - if(strcmp(color, "gray95") == 0) { - rgb->red = 242; - rgb->green = 242; - rgb->blue = 242; - return; - } - if(strcmp(color, "grey95") == 0) { - rgb->red = 242; - rgb->green = 242; - rgb->blue = 242; - return; - } - if(strcmp(color, "gray96") == 0) { - rgb->red = 245; - rgb->green = 245; - rgb->blue = 245; - return; - } - if(strcmp(color, "grey96") == 0) { - rgb->red = 245; - rgb->green = 245; - rgb->blue = 245; - return; - } - if(strcmp(color, "gray97") == 0) { - rgb->red = 247; - rgb->green = 247; - rgb->blue = 247; - return; - } - if(strcmp(color, "grey97") == 0) { - rgb->red = 247; - rgb->green = 247; - rgb->blue = 247; - return; - } - if(strcmp(color, "gray98") == 0) { - rgb->red = 250; - rgb->green = 250; - rgb->blue = 250; - return; - } - if(strcmp(color, "grey98") == 0) { - rgb->red = 250; - rgb->green = 250; - rgb->blue = 250; - return; - } - if(strcmp(color, "gray99") == 0) { - rgb->red = 252; - rgb->green = 252; - rgb->blue = 252; - return; - } - if(strcmp(color, "grey99") == 0) { - rgb->red = 252; - rgb->green = 252; - rgb->blue = 252; - return; - } - if(strcmp(color, "gray100") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "grey100") == 0) { - rgb->red = 255; - rgb->green = 255; - rgb->blue = 255; - return; - } - if(strcmp(color, "dark grey") == 0) { - rgb->red = 169; - rgb->green = 169; - rgb->blue = 169; - return; - } - if(strcmp(color, "DarkGrey") == 0) { - rgb->red = 169; - rgb->green = 169; - rgb->blue = 169; - return; - } - if(strcmp(color, "dark gray") == 0) { - rgb->red = 169; - rgb->green = 169; - rgb->blue = 169; - return; - } - if(strcmp(color, "DarkGray") == 0) { - rgb->red = 169; - rgb->green = 169; - rgb->blue = 169; - return; - } - if(strcmp(color, "dark blue") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 139; - return; - } - if(strcmp(color, "DarkBlue") == 0) { - rgb->red = 0; - rgb->green = 0; - rgb->blue = 139; - return; - } - if(strcmp(color, "dark cyan") == 0) { - rgb->red = 0; - rgb->green = 139; - rgb->blue = 139; - return; - } - if(strcmp(color, "DarkCyan") == 0) { - rgb->red = 0; - rgb->green = 139; - rgb->blue = 139; - return; - } - if(strcmp(color, "dark magenta") == 0) { - rgb->red = 139; - rgb->green = 0; - rgb->blue = 139; - return; - } - if(strcmp(color, "DarkMagenta") == 0) { - rgb->red = 139; - rgb->green = 0; - rgb->blue = 139; - return; - } - if(strcmp(color, "dark red") == 0) { - rgb->red = 139; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "DarkRed") == 0) { - rgb->red = 139; - rgb->green = 0; - rgb->blue = 0; - return; - } - if(strcmp(color, "light green") == 0) { - rgb->red = 144; - rgb->green = 238; - rgb->blue = 144; - return; - } - if(strcmp(color, "LightGreen") == 0) { - rgb->red = 144; - rgb->green = 238; - rgb->blue = 144; - return; - } - if(strcmp(color, "crimson") == 0) { - rgb->red = 220; - rgb->green = 20; - rgb->blue = 60; - return; - } - if(strcmp(color, "indigo") == 0) { - rgb->red = 75; - rgb->green = 0; - rgb->blue = 130; - return; - } - if(strcmp(color, "olive") == 0) { - rgb->red = 128; - rgb->green = 128; - rgb->blue = 0; - return; - } - if(strcmp(color, "rebecca purple") == 0) { - rgb->red = 102; - rgb->green = 51; - rgb->blue = 153; - return; - } - if(strcmp(color, "RebeccaPurple") == 0) { - rgb->red = 102; - rgb->green = 51; - rgb->blue = 153; - return; - } - if(strcmp(color, "silver") == 0) { - rgb->red = 192; - rgb->green = 192; - rgb->blue = 192; - return; - } - if(strcmp(color, "teal") == 0) { - rgb->red = 0; - rgb->green = 128; - rgb->blue = 128; - return; - } - rgb->red = 0; - rgb->green = 0; - rgb->blue = 0; + MwU32 v = shget(colors, color); + rgb->red = (v >> 16) & 0xff; + rgb->green = (v >> 8) & 0xff; + rgb->blue = (v >> 0) & 0xff; +} + +static void add_color(const char* name, int red, int green, int blue) { + MwU32 v = (red << 16) | (green << 8) | (blue << 0); + shput(colors, name, v); +} + +void MwColorTableInit(void) { + sh_new_strdup(colors); + shdefault(colors, 0); + add_color("snow", 255, 250, 250); + add_color("ghost white", 248, 248, 255); + add_color("GhostWhite", 248, 248, 255); + add_color("white smoke", 245, 245, 245); + add_color("WhiteSmoke", 245, 245, 245); + add_color("gainsboro", 220, 220, 220); + add_color("floral white", 255, 250, 240); + add_color("FloralWhite", 255, 250, 240); + add_color("old lace", 253, 245, 230); + add_color("OldLace", 253, 245, 230); + add_color("linen", 250, 240, 230); + add_color("antique white", 250, 235, 215); + add_color("AntiqueWhite", 250, 235, 215); + add_color("papaya whip", 255, 239, 213); + add_color("PapayaWhip", 255, 239, 213); + add_color("blanched almond", 255, 235, 205); + add_color("BlanchedAlmond", 255, 235, 205); + add_color("bisque", 255, 228, 196); + add_color("peach puff", 255, 218, 185); + add_color("PeachPuff", 255, 218, 185); + add_color("navajo white", 255, 222, 173); + add_color("NavajoWhite", 255, 222, 173); + add_color("moccasin", 255, 228, 181); + add_color("cornsilk", 255, 248, 220); + add_color("ivory", 255, 255, 240); + add_color("lemon chiffon", 255, 250, 205); + add_color("LemonChiffon", 255, 250, 205); + add_color("seashell", 255, 245, 238); + add_color("honeydew", 240, 255, 240); + add_color("mint cream", 245, 255, 250); + add_color("MintCream", 245, 255, 250); + add_color("azure", 240, 255, 255); + add_color("alice blue", 240, 248, 255); + add_color("AliceBlue", 240, 248, 255); + add_color("lavender", 230, 230, 250); + add_color("lavender blush", 255, 240, 245); + add_color("LavenderBlush", 255, 240, 245); + add_color("misty rose", 255, 228, 225); + add_color("MistyRose", 255, 228, 225); + add_color("white", 255, 255, 255); + add_color("black", 0, 0, 0); + add_color("dark slate gray", 47, 79, 79); + add_color("DarkSlateGray", 47, 79, 79); + add_color("dark slate grey", 47, 79, 79); + add_color("DarkSlateGrey", 47, 79, 79); + add_color("dim gray", 105, 105, 105); + add_color("DimGray", 105, 105, 105); + add_color("dim grey", 105, 105, 105); + add_color("DimGrey", 105, 105, 105); + add_color("slate gray", 112, 128, 144); + add_color("SlateGray", 112, 128, 144); + add_color("slate grey", 112, 128, 144); + add_color("SlateGrey", 112, 128, 144); + add_color("light slate gray", 119, 136, 153); + add_color("LightSlateGray", 119, 136, 153); + add_color("light slate grey", 119, 136, 153); + add_color("LightSlateGrey", 119, 136, 153); + add_color("gray", 190, 190, 190); + add_color("grey", 190, 190, 190); + add_color("x11 gray", 190, 190, 190); + add_color("X11Gray", 190, 190, 190); + add_color("x11 grey", 190, 190, 190); + add_color("X11Grey", 190, 190, 190); + add_color("web gray", 128, 128, 128); + add_color("WebGray", 128, 128, 128); + add_color("web grey", 128, 128, 128); + add_color("WebGrey", 128, 128, 128); + add_color("light grey", 211, 211, 211); + add_color("LightGrey", 211, 211, 211); + add_color("light gray", 211, 211, 211); + add_color("LightGray", 211, 211, 211); + add_color("midnight blue", 25, 25, 112); + add_color("MidnightBlue", 25, 25, 112); + add_color("navy", 0, 0, 128); + add_color("navy blue", 0, 0, 128); + add_color("NavyBlue", 0, 0, 128); + add_color("cornflower blue", 100, 149, 237); + add_color("CornflowerBlue", 100, 149, 237); + add_color("dark slate blue", 72, 61, 139); + add_color("DarkSlateBlue", 72, 61, 139); + add_color("slate blue", 106, 90, 205); + add_color("SlateBlue", 106, 90, 205); + add_color("medium slate blue", 123, 104, 238); + add_color("MediumSlateBlue", 123, 104, 238); + add_color("light slate blue", 132, 112, 255); + add_color("LightSlateBlue", 132, 112, 255); + add_color("medium blue", 0, 0, 205); + add_color("MediumBlue", 0, 0, 205); + add_color("royal blue", 65, 105, 225); + add_color("RoyalBlue", 65, 105, 225); + add_color("blue", 0, 0, 255); + add_color("dodger blue", 30, 144, 255); + add_color("DodgerBlue", 30, 144, 255); + add_color("deep sky blue", 0, 191, 255); + add_color("DeepSkyBlue", 0, 191, 255); + add_color("sky blue", 135, 206, 235); + add_color("SkyBlue", 135, 206, 235); + add_color("light sky blue", 135, 206, 250); + add_color("LightSkyBlue", 135, 206, 250); + add_color("steel blue", 70, 130, 180); + add_color("SteelBlue", 70, 130, 180); + add_color("light steel blue", 176, 196, 222); + add_color("LightSteelBlue", 176, 196, 222); + add_color("light blue", 173, 216, 230); + add_color("LightBlue", 173, 216, 230); + add_color("powder blue", 176, 224, 230); + add_color("PowderBlue", 176, 224, 230); + add_color("pale turquoise", 175, 238, 238); + add_color("PaleTurquoise", 175, 238, 238); + add_color("dark turquoise", 0, 206, 209); + add_color("DarkTurquoise", 0, 206, 209); + add_color("medium turquoise", 72, 209, 204); + add_color("MediumTurquoise", 72, 209, 204); + add_color("turquoise", 64, 224, 208); + add_color("cyan", 0, 255, 255); + add_color("aqua", 0, 255, 255); + add_color("light cyan", 224, 255, 255); + add_color("LightCyan", 224, 255, 255); + add_color("cadet blue", 95, 158, 160); + add_color("CadetBlue", 95, 158, 160); + add_color("medium aquamarine", 102, 205, 170); + add_color("MediumAquamarine", 102, 205, 170); + add_color("aquamarine", 127, 255, 212); + add_color("dark green", 0, 100, 0); + add_color("DarkGreen", 0, 100, 0); + add_color("dark olive green", 85, 107, 47); + add_color("DarkOliveGreen", 85, 107, 47); + add_color("dark sea green", 143, 188, 143); + add_color("DarkSeaGreen", 143, 188, 143); + add_color("sea green", 46, 139, 87); + add_color("SeaGreen", 46, 139, 87); + add_color("medium sea green", 60, 179, 113); + add_color("MediumSeaGreen", 60, 179, 113); + add_color("light sea green", 32, 178, 170); + add_color("LightSeaGreen", 32, 178, 170); + add_color("pale green", 152, 251, 152); + add_color("PaleGreen", 152, 251, 152); + add_color("spring green", 0, 255, 127); + add_color("SpringGreen", 0, 255, 127); + add_color("lawn green", 124, 252, 0); + add_color("LawnGreen", 124, 252, 0); + add_color("green", 0, 255, 0); + add_color("lime", 0, 255, 0); + add_color("x11 green", 0, 255, 0); + add_color("X11Green", 0, 255, 0); + add_color("web green", 0, 128, 0); + add_color("WebGreen", 0, 128, 0); + add_color("chartreuse", 127, 255, 0); + add_color("medium spring green", 0, 250, 154); + add_color("MediumSpringGreen", 0, 250, 154); + add_color("green yellow", 173, 255, 47); + add_color("GreenYellow", 173, 255, 47); + add_color("lime green", 50, 205, 50); + add_color("LimeGreen", 50, 205, 50); + add_color("yellow green", 154, 205, 50); + add_color("YellowGreen", 154, 205, 50); + add_color("forest green", 34, 139, 34); + add_color("ForestGreen", 34, 139, 34); + add_color("olive drab", 107, 142, 35); + add_color("OliveDrab", 107, 142, 35); + add_color("dark khaki", 189, 183, 107); + add_color("DarkKhaki", 189, 183, 107); + add_color("khaki", 240, 230, 140); + add_color("pale goldenrod", 238, 232, 170); + add_color("PaleGoldenrod", 238, 232, 170); + add_color("light goldenrod yellow", 250, 250, 210); + add_color("LightGoldenrodYellow", 250, 250, 210); + add_color("light yellow", 255, 255, 224); + add_color("LightYellow", 255, 255, 224); + add_color("yellow", 255, 255, 0); + add_color("gold", 255, 215, 0); + add_color("light goldenrod", 238, 221, 130); + add_color("LightGoldenrod", 238, 221, 130); + add_color("goldenrod", 218, 165, 32); + add_color("dark goldenrod", 184, 134, 11); + add_color("DarkGoldenrod", 184, 134, 11); + add_color("rosy brown", 188, 143, 143); + add_color("RosyBrown", 188, 143, 143); + add_color("indian red", 205, 92, 92); + add_color("IndianRed", 205, 92, 92); + add_color("saddle brown", 139, 69, 19); + add_color("SaddleBrown", 139, 69, 19); + add_color("sienna", 160, 82, 45); + add_color("peru", 205, 133, 63); + add_color("burlywood", 222, 184, 135); + add_color("beige", 245, 245, 220); + add_color("wheat", 245, 222, 179); + add_color("sandy brown", 244, 164, 96); + add_color("SandyBrown", 244, 164, 96); + add_color("tan", 210, 180, 140); + add_color("chocolate", 210, 105, 30); + add_color("firebrick", 178, 34, 34); + add_color("brown", 165, 42, 42); + add_color("dark salmon", 233, 150, 122); + add_color("DarkSalmon", 233, 150, 122); + add_color("salmon", 250, 128, 114); + add_color("light salmon", 255, 160, 122); + add_color("LightSalmon", 255, 160, 122); + add_color("orange", 255, 165, 0); + add_color("dark orange", 255, 140, 0); + add_color("DarkOrange", 255, 140, 0); + add_color("coral", 255, 127, 80); + add_color("light coral", 240, 128, 128); + add_color("LightCoral", 240, 128, 128); + add_color("tomato", 255, 99, 71); + add_color("orange red", 255, 69, 0); + add_color("OrangeRed", 255, 69, 0); + add_color("red", 255, 0, 0); + add_color("hot pink", 255, 105, 180); + add_color("HotPink", 255, 105, 180); + add_color("deep pink", 255, 20, 147); + add_color("DeepPink", 255, 20, 147); + add_color("pink", 255, 192, 203); + add_color("light pink", 255, 182, 193); + add_color("LightPink", 255, 182, 193); + add_color("pale violet red", 219, 112, 147); + add_color("PaleVioletRed", 219, 112, 147); + add_color("maroon", 176, 48, 96); + add_color("x11 maroon", 176, 48, 96); + add_color("X11Maroon", 176, 48, 96); + add_color("web maroon", 128, 0, 0); + add_color("WebMaroon", 128, 0, 0); + add_color("medium violet red", 199, 21, 133); + add_color("MediumVioletRed", 199, 21, 133); + add_color("violet red", 208, 32, 144); + add_color("VioletRed", 208, 32, 144); + add_color("magenta", 255, 0, 255); + add_color("fuchsia", 255, 0, 255); + add_color("violet", 238, 130, 238); + add_color("plum", 221, 160, 221); + add_color("orchid", 218, 112, 214); + add_color("medium orchid", 186, 85, 211); + add_color("MediumOrchid", 186, 85, 211); + add_color("dark orchid", 153, 50, 204); + add_color("DarkOrchid", 153, 50, 204); + add_color("dark violet", 148, 0, 211); + add_color("DarkViolet", 148, 0, 211); + add_color("blue violet", 138, 43, 226); + add_color("BlueViolet", 138, 43, 226); + add_color("purple", 160, 32, 240); + add_color("x11 purple", 160, 32, 240); + add_color("X11Purple", 160, 32, 240); + add_color("web purple", 128, 0, 128); + add_color("WebPurple", 128, 0, 128); + add_color("medium purple", 147, 112, 219); + add_color("MediumPurple", 147, 112, 219); + add_color("thistle", 216, 191, 216); + add_color("snow1", 255, 250, 250); + add_color("snow2", 238, 233, 233); + add_color("snow3", 205, 201, 201); + add_color("snow4", 139, 137, 137); + add_color("seashell1", 255, 245, 238); + add_color("seashell2", 238, 229, 222); + add_color("seashell3", 205, 197, 191); + add_color("seashell4", 139, 134, 130); + add_color("AntiqueWhite1", 255, 239, 219); + add_color("AntiqueWhite2", 238, 223, 204); + add_color("AntiqueWhite3", 205, 192, 176); + add_color("AntiqueWhite4", 139, 131, 120); + add_color("bisque1", 255, 228, 196); + add_color("bisque2", 238, 213, 183); + add_color("bisque3", 205, 183, 158); + add_color("bisque4", 139, 125, 107); + add_color("PeachPuff1", 255, 218, 185); + add_color("PeachPuff2", 238, 203, 173); + add_color("PeachPuff3", 205, 175, 149); + add_color("PeachPuff4", 139, 119, 101); + add_color("NavajoWhite1", 255, 222, 173); + add_color("NavajoWhite2", 238, 207, 161); + add_color("NavajoWhite3", 205, 179, 139); + add_color("NavajoWhite4", 139, 121, 94); + add_color("LemonChiffon1", 255, 250, 205); + add_color("LemonChiffon2", 238, 233, 191); + add_color("LemonChiffon3", 205, 201, 165); + add_color("LemonChiffon4", 139, 137, 112); + add_color("cornsilk1", 255, 248, 220); + add_color("cornsilk2", 238, 232, 205); + add_color("cornsilk3", 205, 200, 177); + add_color("cornsilk4", 139, 136, 120); + add_color("ivory1", 255, 255, 240); + add_color("ivory2", 238, 238, 224); + add_color("ivory3", 205, 205, 193); + add_color("ivory4", 139, 139, 131); + add_color("honeydew1", 240, 255, 240); + add_color("honeydew2", 224, 238, 224); + add_color("honeydew3", 193, 205, 193); + add_color("honeydew4", 131, 139, 131); + add_color("LavenderBlush1", 255, 240, 245); + add_color("LavenderBlush2", 238, 224, 229); + add_color("LavenderBlush3", 205, 193, 197); + add_color("LavenderBlush4", 139, 131, 134); + add_color("MistyRose1", 255, 228, 225); + add_color("MistyRose2", 238, 213, 210); + add_color("MistyRose3", 205, 183, 181); + add_color("MistyRose4", 139, 125, 123); + add_color("azure1", 240, 255, 255); + add_color("azure2", 224, 238, 238); + add_color("azure3", 193, 205, 205); + add_color("azure4", 131, 139, 139); + add_color("SlateBlue1", 131, 111, 255); + add_color("SlateBlue2", 122, 103, 238); + add_color("SlateBlue3", 105, 89, 205); + add_color("SlateBlue4", 71, 60, 139); + add_color("RoyalBlue1", 72, 118, 255); + add_color("RoyalBlue2", 67, 110, 238); + add_color("RoyalBlue3", 58, 95, 205); + add_color("RoyalBlue4", 39, 64, 139); + add_color("blue1", 0, 0, 255); + add_color("blue2", 0, 0, 238); + add_color("blue3", 0, 0, 205); + add_color("blue4", 0, 0, 139); + add_color("DodgerBlue1", 30, 144, 255); + add_color("DodgerBlue2", 28, 134, 238); + add_color("DodgerBlue3", 24, 116, 205); + add_color("DodgerBlue4", 16, 78, 139); + add_color("SteelBlue1", 99, 184, 255); + add_color("SteelBlue2", 92, 172, 238); + add_color("SteelBlue3", 79, 148, 205); + add_color("SteelBlue4", 54, 100, 139); + add_color("DeepSkyBlue1", 0, 191, 255); + add_color("DeepSkyBlue2", 0, 178, 238); + add_color("DeepSkyBlue3", 0, 154, 205); + add_color("DeepSkyBlue4", 0, 104, 139); + add_color("SkyBlue1", 135, 206, 255); + add_color("SkyBlue2", 126, 192, 238); + add_color("SkyBlue3", 108, 166, 205); + add_color("SkyBlue4", 74, 112, 139); + add_color("LightSkyBlue1", 176, 226, 255); + add_color("LightSkyBlue2", 164, 211, 238); + add_color("LightSkyBlue3", 141, 182, 205); + add_color("LightSkyBlue4", 96, 123, 139); + add_color("SlateGray1", 198, 226, 255); + add_color("SlateGray2", 185, 211, 238); + add_color("SlateGray3", 159, 182, 205); + add_color("SlateGray4", 108, 123, 139); + add_color("LightSteelBlue1", 202, 225, 255); + add_color("LightSteelBlue2", 188, 210, 238); + add_color("LightSteelBlue3", 162, 181, 205); + add_color("LightSteelBlue4", 110, 123, 139); + add_color("LightBlue1", 191, 239, 255); + add_color("LightBlue2", 178, 223, 238); + add_color("LightBlue3", 154, 192, 205); + add_color("LightBlue4", 104, 131, 139); + add_color("LightCyan1", 224, 255, 255); + add_color("LightCyan2", 209, 238, 238); + add_color("LightCyan3", 180, 205, 205); + add_color("LightCyan4", 122, 139, 139); + add_color("PaleTurquoise1", 187, 255, 255); + add_color("PaleTurquoise2", 174, 238, 238); + add_color("PaleTurquoise3", 150, 205, 205); + add_color("PaleTurquoise4", 102, 139, 139); + add_color("CadetBlue1", 152, 245, 255); + add_color("CadetBlue2", 142, 229, 238); + add_color("CadetBlue3", 122, 197, 205); + add_color("CadetBlue4", 83, 134, 139); + add_color("turquoise1", 0, 245, 255); + add_color("turquoise2", 0, 229, 238); + add_color("turquoise3", 0, 197, 205); + add_color("turquoise4", 0, 134, 139); + add_color("cyan1", 0, 255, 255); + add_color("cyan2", 0, 238, 238); + add_color("cyan3", 0, 205, 205); + add_color("cyan4", 0, 139, 139); + add_color("DarkSlateGray1", 151, 255, 255); + add_color("DarkSlateGray2", 141, 238, 238); + add_color("DarkSlateGray3", 121, 205, 205); + add_color("DarkSlateGray4", 82, 139, 139); + add_color("aquamarine1", 127, 255, 212); + add_color("aquamarine2", 118, 238, 198); + add_color("aquamarine3", 102, 205, 170); + add_color("aquamarine4", 69, 139, 116); + add_color("DarkSeaGreen1", 193, 255, 193); + add_color("DarkSeaGreen2", 180, 238, 180); + add_color("DarkSeaGreen3", 155, 205, 155); + add_color("DarkSeaGreen4", 105, 139, 105); + add_color("SeaGreen1", 84, 255, 159); + add_color("SeaGreen2", 78, 238, 148); + add_color("SeaGreen3", 67, 205, 128); + add_color("SeaGreen4", 46, 139, 87); + add_color("PaleGreen1", 154, 255, 154); + add_color("PaleGreen2", 144, 238, 144); + add_color("PaleGreen3", 124, 205, 124); + add_color("PaleGreen4", 84, 139, 84); + add_color("SpringGreen1", 0, 255, 127); + add_color("SpringGreen2", 0, 238, 118); + add_color("SpringGreen3", 0, 205, 102); + add_color("SpringGreen4", 0, 139, 69); + add_color("green1", 0, 255, 0); + add_color("green2", 0, 238, 0); + add_color("green3", 0, 205, 0); + add_color("green4", 0, 139, 0); + add_color("chartreuse1", 127, 255, 0); + add_color("chartreuse2", 118, 238, 0); + add_color("chartreuse3", 102, 205, 0); + add_color("chartreuse4", 69, 139, 0); + add_color("OliveDrab1", 192, 255, 62); + add_color("OliveDrab2", 179, 238, 58); + add_color("OliveDrab3", 154, 205, 50); + add_color("OliveDrab4", 105, 139, 34); + add_color("DarkOliveGreen1", 202, 255, 112); + add_color("DarkOliveGreen2", 188, 238, 104); + add_color("DarkOliveGreen3", 162, 205, 90); + add_color("DarkOliveGreen4", 110, 139, 61); + add_color("khaki1", 255, 246, 143); + add_color("khaki2", 238, 230, 133); + add_color("khaki3", 205, 198, 115); + add_color("khaki4", 139, 134, 78); + add_color("LightGoldenrod1", 255, 236, 139); + add_color("LightGoldenrod2", 238, 220, 130); + add_color("LightGoldenrod3", 205, 190, 112); + add_color("LightGoldenrod4", 139, 129, 76); + add_color("LightYellow1", 255, 255, 224); + add_color("LightYellow2", 238, 238, 209); + add_color("LightYellow3", 205, 205, 180); + add_color("LightYellow4", 139, 139, 122); + add_color("yellow1", 255, 255, 0); + add_color("yellow2", 238, 238, 0); + add_color("yellow3", 205, 205, 0); + add_color("yellow4", 139, 139, 0); + add_color("gold1", 255, 215, 0); + add_color("gold2", 238, 201, 0); + add_color("gold3", 205, 173, 0); + add_color("gold4", 139, 117, 0); + add_color("goldenrod1", 255, 193, 37); + add_color("goldenrod2", 238, 180, 34); + add_color("goldenrod3", 205, 155, 29); + add_color("goldenrod4", 139, 105, 20); + add_color("DarkGoldenrod1", 255, 185, 15); + add_color("DarkGoldenrod2", 238, 173, 14); + add_color("DarkGoldenrod3", 205, 149, 12); + add_color("DarkGoldenrod4", 139, 101, 8); + add_color("RosyBrown1", 255, 193, 193); + add_color("RosyBrown2", 238, 180, 180); + add_color("RosyBrown3", 205, 155, 155); + add_color("RosyBrown4", 139, 105, 105); + add_color("IndianRed1", 255, 106, 106); + add_color("IndianRed2", 238, 99, 99); + add_color("IndianRed3", 205, 85, 85); + add_color("IndianRed4", 139, 58, 58); + add_color("sienna1", 255, 130, 71); + add_color("sienna2", 238, 121, 66); + add_color("sienna3", 205, 104, 57); + add_color("sienna4", 139, 71, 38); + add_color("burlywood1", 255, 211, 155); + add_color("burlywood2", 238, 197, 145); + add_color("burlywood3", 205, 170, 125); + add_color("burlywood4", 139, 115, 85); + add_color("wheat1", 255, 231, 186); + add_color("wheat2", 238, 216, 174); + add_color("wheat3", 205, 186, 150); + add_color("wheat4", 139, 126, 102); + add_color("tan1", 255, 165, 79); + add_color("tan2", 238, 154, 73); + add_color("tan3", 205, 133, 63); + add_color("tan4", 139, 90, 43); + add_color("chocolate1", 255, 127, 36); + add_color("chocolate2", 238, 118, 33); + add_color("chocolate3", 205, 102, 29); + add_color("chocolate4", 139, 69, 19); + add_color("firebrick1", 255, 48, 48); + add_color("firebrick2", 238, 44, 44); + add_color("firebrick3", 205, 38, 38); + add_color("firebrick4", 139, 26, 26); + add_color("brown1", 255, 64, 64); + add_color("brown2", 238, 59, 59); + add_color("brown3", 205, 51, 51); + add_color("brown4", 139, 35, 35); + add_color("salmon1", 255, 140, 105); + add_color("salmon2", 238, 130, 98); + add_color("salmon3", 205, 112, 84); + add_color("salmon4", 139, 76, 57); + add_color("LightSalmon1", 255, 160, 122); + add_color("LightSalmon2", 238, 149, 114); + add_color("LightSalmon3", 205, 129, 98); + add_color("LightSalmon4", 139, 87, 66); + add_color("orange1", 255, 165, 0); + add_color("orange2", 238, 154, 0); + add_color("orange3", 205, 133, 0); + add_color("orange4", 139, 90, 0); + add_color("DarkOrange1", 255, 127, 0); + add_color("DarkOrange2", 238, 118, 0); + add_color("DarkOrange3", 205, 102, 0); + add_color("DarkOrange4", 139, 69, 0); + add_color("coral1", 255, 114, 86); + add_color("coral2", 238, 106, 80); + add_color("coral3", 205, 91, 69); + add_color("coral4", 139, 62, 47); + add_color("tomato1", 255, 99, 71); + add_color("tomato2", 238, 92, 66); + add_color("tomato3", 205, 79, 57); + add_color("tomato4", 139, 54, 38); + add_color("OrangeRed1", 255, 69, 0); + add_color("OrangeRed2", 238, 64, 0); + add_color("OrangeRed3", 205, 55, 0); + add_color("OrangeRed4", 139, 37, 0); + add_color("red1", 255, 0, 0); + add_color("red2", 238, 0, 0); + add_color("red3", 205, 0, 0); + add_color("red4", 139, 0, 0); + add_color("DeepPink1", 255, 20, 147); + add_color("DeepPink2", 238, 18, 137); + add_color("DeepPink3", 205, 16, 118); + add_color("DeepPink4", 139, 10, 80); + add_color("HotPink1", 255, 110, 180); + add_color("HotPink2", 238, 106, 167); + add_color("HotPink3", 205, 96, 144); + add_color("HotPink4", 139, 58, 98); + add_color("pink1", 255, 181, 197); + add_color("pink2", 238, 169, 184); + add_color("pink3", 205, 145, 158); + add_color("pink4", 139, 99, 108); + add_color("LightPink1", 255, 174, 185); + add_color("LightPink2", 238, 162, 173); + add_color("LightPink3", 205, 140, 149); + add_color("LightPink4", 139, 95, 101); + add_color("PaleVioletRed1", 255, 130, 171); + add_color("PaleVioletRed2", 238, 121, 159); + add_color("PaleVioletRed3", 205, 104, 137); + add_color("PaleVioletRed4", 139, 71, 93); + add_color("maroon1", 255, 52, 179); + add_color("maroon2", 238, 48, 167); + add_color("maroon3", 205, 41, 144); + add_color("maroon4", 139, 28, 98); + add_color("VioletRed1", 255, 62, 150); + add_color("VioletRed2", 238, 58, 140); + add_color("VioletRed3", 205, 50, 120); + add_color("VioletRed4", 139, 34, 82); + add_color("magenta1", 255, 0, 255); + add_color("magenta2", 238, 0, 238); + add_color("magenta3", 205, 0, 205); + add_color("magenta4", 139, 0, 139); + add_color("orchid1", 255, 131, 250); + add_color("orchid2", 238, 122, 233); + add_color("orchid3", 205, 105, 201); + add_color("orchid4", 139, 71, 137); + add_color("plum1", 255, 187, 255); + add_color("plum2", 238, 174, 238); + add_color("plum3", 205, 150, 205); + add_color("plum4", 139, 102, 139); + add_color("MediumOrchid1", 224, 102, 255); + add_color("MediumOrchid2", 209, 95, 238); + add_color("MediumOrchid3", 180, 82, 205); + add_color("MediumOrchid4", 122, 55, 139); + add_color("DarkOrchid1", 191, 62, 255); + add_color("DarkOrchid2", 178, 58, 238); + add_color("DarkOrchid3", 154, 50, 205); + add_color("DarkOrchid4", 104, 34, 139); + add_color("purple1", 155, 48, 255); + add_color("purple2", 145, 44, 238); + add_color("purple3", 125, 38, 205); + add_color("purple4", 85, 26, 139); + add_color("MediumPurple1", 171, 130, 255); + add_color("MediumPurple2", 159, 121, 238); + add_color("MediumPurple3", 137, 104, 205); + add_color("MediumPurple4", 93, 71, 139); + add_color("thistle1", 255, 225, 255); + add_color("thistle2", 238, 210, 238); + add_color("thistle3", 205, 181, 205); + add_color("thistle4", 139, 123, 139); + add_color("gray0", 0, 0, 0); + add_color("grey0", 0, 0, 0); + add_color("gray1", 3, 3, 3); + add_color("grey1", 3, 3, 3); + add_color("gray2", 5, 5, 5); + add_color("grey2", 5, 5, 5); + add_color("gray3", 8, 8, 8); + add_color("grey3", 8, 8, 8); + add_color("gray4", 10, 10, 10); + add_color("grey4", 10, 10, 10); + add_color("gray5", 13, 13, 13); + add_color("grey5", 13, 13, 13); + add_color("gray6", 15, 15, 15); + add_color("grey6", 15, 15, 15); + add_color("gray7", 18, 18, 18); + add_color("grey7", 18, 18, 18); + add_color("gray8", 20, 20, 20); + add_color("grey8", 20, 20, 20); + add_color("gray9", 23, 23, 23); + add_color("grey9", 23, 23, 23); + add_color("gray10", 26, 26, 26); + add_color("grey10", 26, 26, 26); + add_color("gray11", 28, 28, 28); + add_color("grey11", 28, 28, 28); + add_color("gray12", 31, 31, 31); + add_color("grey12", 31, 31, 31); + add_color("gray13", 33, 33, 33); + add_color("grey13", 33, 33, 33); + add_color("gray14", 36, 36, 36); + add_color("grey14", 36, 36, 36); + add_color("gray15", 38, 38, 38); + add_color("grey15", 38, 38, 38); + add_color("gray16", 41, 41, 41); + add_color("grey16", 41, 41, 41); + add_color("gray17", 43, 43, 43); + add_color("grey17", 43, 43, 43); + add_color("gray18", 46, 46, 46); + add_color("grey18", 46, 46, 46); + add_color("gray19", 48, 48, 48); + add_color("grey19", 48, 48, 48); + add_color("gray20", 51, 51, 51); + add_color("grey20", 51, 51, 51); + add_color("gray21", 54, 54, 54); + add_color("grey21", 54, 54, 54); + add_color("gray22", 56, 56, 56); + add_color("grey22", 56, 56, 56); + add_color("gray23", 59, 59, 59); + add_color("grey23", 59, 59, 59); + add_color("gray24", 61, 61, 61); + add_color("grey24", 61, 61, 61); + add_color("gray25", 64, 64, 64); + add_color("grey25", 64, 64, 64); + add_color("gray26", 66, 66, 66); + add_color("grey26", 66, 66, 66); + add_color("gray27", 69, 69, 69); + add_color("grey27", 69, 69, 69); + add_color("gray28", 71, 71, 71); + add_color("grey28", 71, 71, 71); + add_color("gray29", 74, 74, 74); + add_color("grey29", 74, 74, 74); + add_color("gray30", 77, 77, 77); + add_color("grey30", 77, 77, 77); + add_color("gray31", 79, 79, 79); + add_color("grey31", 79, 79, 79); + add_color("gray32", 82, 82, 82); + add_color("grey32", 82, 82, 82); + add_color("gray33", 84, 84, 84); + add_color("grey33", 84, 84, 84); + add_color("gray34", 87, 87, 87); + add_color("grey34", 87, 87, 87); + add_color("gray35", 89, 89, 89); + add_color("grey35", 89, 89, 89); + add_color("gray36", 92, 92, 92); + add_color("grey36", 92, 92, 92); + add_color("gray37", 94, 94, 94); + add_color("grey37", 94, 94, 94); + add_color("gray38", 97, 97, 97); + add_color("grey38", 97, 97, 97); + add_color("gray39", 99, 99, 99); + add_color("grey39", 99, 99, 99); + add_color("gray40", 102, 102, 102); + add_color("grey40", 102, 102, 102); + add_color("gray41", 105, 105, 105); + add_color("grey41", 105, 105, 105); + add_color("gray42", 107, 107, 107); + add_color("grey42", 107, 107, 107); + add_color("gray43", 110, 110, 110); + add_color("grey43", 110, 110, 110); + add_color("gray44", 112, 112, 112); + add_color("grey44", 112, 112, 112); + add_color("gray45", 115, 115, 115); + add_color("grey45", 115, 115, 115); + add_color("gray46", 117, 117, 117); + add_color("grey46", 117, 117, 117); + add_color("gray47", 120, 120, 120); + add_color("grey47", 120, 120, 120); + add_color("gray48", 122, 122, 122); + add_color("grey48", 122, 122, 122); + add_color("gray49", 125, 125, 125); + add_color("grey49", 125, 125, 125); + add_color("gray50", 127, 127, 127); + add_color("grey50", 127, 127, 127); + add_color("gray51", 130, 130, 130); + add_color("grey51", 130, 130, 130); + add_color("gray52", 133, 133, 133); + add_color("grey52", 133, 133, 133); + add_color("gray53", 135, 135, 135); + add_color("grey53", 135, 135, 135); + add_color("gray54", 138, 138, 138); + add_color("grey54", 138, 138, 138); + add_color("gray55", 140, 140, 140); + add_color("grey55", 140, 140, 140); + add_color("gray56", 143, 143, 143); + add_color("grey56", 143, 143, 143); + add_color("gray57", 145, 145, 145); + add_color("grey57", 145, 145, 145); + add_color("gray58", 148, 148, 148); + add_color("grey58", 148, 148, 148); + add_color("gray59", 150, 150, 150); + add_color("grey59", 150, 150, 150); + add_color("gray60", 153, 153, 153); + add_color("grey60", 153, 153, 153); + add_color("gray61", 156, 156, 156); + add_color("grey61", 156, 156, 156); + add_color("gray62", 158, 158, 158); + add_color("grey62", 158, 158, 158); + add_color("gray63", 161, 161, 161); + add_color("grey63", 161, 161, 161); + add_color("gray64", 163, 163, 163); + add_color("grey64", 163, 163, 163); + add_color("gray65", 166, 166, 166); + add_color("grey65", 166, 166, 166); + add_color("gray66", 168, 168, 168); + add_color("grey66", 168, 168, 168); + add_color("gray67", 171, 171, 171); + add_color("grey67", 171, 171, 171); + add_color("gray68", 173, 173, 173); + add_color("grey68", 173, 173, 173); + add_color("gray69", 176, 176, 176); + add_color("grey69", 176, 176, 176); + add_color("gray70", 179, 179, 179); + add_color("grey70", 179, 179, 179); + add_color("gray71", 181, 181, 181); + add_color("grey71", 181, 181, 181); + add_color("gray72", 184, 184, 184); + add_color("grey72", 184, 184, 184); + add_color("gray73", 186, 186, 186); + add_color("grey73", 186, 186, 186); + add_color("gray74", 189, 189, 189); + add_color("grey74", 189, 189, 189); + add_color("gray75", 191, 191, 191); + add_color("grey75", 191, 191, 191); + add_color("gray76", 194, 194, 194); + add_color("grey76", 194, 194, 194); + add_color("gray77", 196, 196, 196); + add_color("grey77", 196, 196, 196); + add_color("gray78", 199, 199, 199); + add_color("grey78", 199, 199, 199); + add_color("gray79", 201, 201, 201); + add_color("grey79", 201, 201, 201); + add_color("gray80", 204, 204, 204); + add_color("grey80", 204, 204, 204); + add_color("gray81", 207, 207, 207); + add_color("grey81", 207, 207, 207); + add_color("gray82", 209, 209, 209); + add_color("grey82", 209, 209, 209); + add_color("gray83", 212, 212, 212); + add_color("grey83", 212, 212, 212); + add_color("gray84", 214, 214, 214); + add_color("grey84", 214, 214, 214); + add_color("gray85", 217, 217, 217); + add_color("grey85", 217, 217, 217); + add_color("gray86", 219, 219, 219); + add_color("grey86", 219, 219, 219); + add_color("gray87", 222, 222, 222); + add_color("grey87", 222, 222, 222); + add_color("gray88", 224, 224, 224); + add_color("grey88", 224, 224, 224); + add_color("gray89", 227, 227, 227); + add_color("grey89", 227, 227, 227); + add_color("gray90", 229, 229, 229); + add_color("grey90", 229, 229, 229); + add_color("gray91", 232, 232, 232); + add_color("grey91", 232, 232, 232); + add_color("gray92", 235, 235, 235); + add_color("grey92", 235, 235, 235); + add_color("gray93", 237, 237, 237); + add_color("grey93", 237, 237, 237); + add_color("gray94", 240, 240, 240); + add_color("grey94", 240, 240, 240); + add_color("gray95", 242, 242, 242); + add_color("grey95", 242, 242, 242); + add_color("gray96", 245, 245, 245); + add_color("grey96", 245, 245, 245); + add_color("gray97", 247, 247, 247); + add_color("grey97", 247, 247, 247); + add_color("gray98", 250, 250, 250); + add_color("grey98", 250, 250, 250); + add_color("gray99", 252, 252, 252); + add_color("grey99", 252, 252, 252); + add_color("gray100", 255, 255, 255); + add_color("grey100", 255, 255, 255); + add_color("dark grey", 169, 169, 169); + add_color("DarkGrey", 169, 169, 169); + add_color("dark gray", 169, 169, 169); + add_color("DarkGray", 169, 169, 169); + add_color("dark blue", 0, 0, 139); + add_color("DarkBlue", 0, 0, 139); + add_color("dark cyan", 0, 139, 139); + add_color("DarkCyan", 0, 139, 139); + add_color("dark magenta", 139, 0, 139); + add_color("DarkMagenta", 139, 0, 139); + add_color("dark red", 139, 0, 0); + add_color("DarkRed", 139, 0, 0); + add_color("light green", 144, 238, 144); + add_color("LightGreen", 144, 238, 144); + add_color("crimson", 220, 20, 60); + add_color("indigo", 75, 0, 130); + add_color("olive", 128, 128, 0); + add_color("rebecca purple", 102, 51, 153); + add_color("RebeccaPurple", 102, 51, 153); + add_color("silver", 192, 192, 192); + add_color("teal", 0, 128, 128); } diff --git a/src/core.c b/src/core.c index db81a2b..c27b1a6 100644 --- a/src/core.c +++ b/src/core.c @@ -6,6 +6,8 @@ #define PERIODIC #endif +#define RESIZE_ON_TICK + #define DRAW(handle) \ { \ MwLLBeginDraw(handle->lowlevel); \ @@ -18,7 +20,17 @@ MwLLEndDraw(handle->lowlevel); \ } -static void MWAPI MwVaListApply_Internal(MwWidget handle, va_list va, int only_early); +#define RESIZE(handle) \ + { \ + int RESIZE_i; \ + MwDispatchUserHandler(handle, MwNresizeHandler, NULL); \ + for(RESIZE_i = 0; RESIZE_i < arrlen(handle->children); RESIZE_i++) { \ + MwDispatch(handle->children[RESIZE_i], parent_resize); \ + } \ + MwDispatch(handle, resize); \ + } + +static void MWAPI MwVaListApply_Internal(MwWidget handle, va_list va, int only_early); static MwWidget MWAPI MwCreateWidget_Internal(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height, int do_prop, va_list prop); static void lldrawhandler(MwLL handle, void* data) { @@ -57,6 +69,7 @@ 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; if(p->button == MwMOUSE_LEFT) h->pressed = 0; h->mouse_point.x = p->point.x; @@ -70,6 +83,7 @@ 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; if(p->button == MwMOUSE_LEFT) h->pressed = 1; h->mouse_point.x = p->point.x; @@ -81,16 +95,35 @@ static void lldownhandler(MwLL handle, void* data) { static void llresizehandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - int i; +#ifdef RESIZE_ON_TICK + MwWidget top; +#endif (void)data; - MwDispatchUserHandler(h, MwNresizeHandler, NULL); - for(i = 0; i < arrlen(h->children); i++) { - MwDispatch(h->children[i], parent_resize); - MwDispatch(h->children[i], draw); +#ifdef RESIZE_ON_TICK + top = h; + while(top != NULL) { + if(top->top_step) { + break; + } + + top = top->parent; } - MwDispatch(h, resize); + + if(top == NULL) { + RESIZE(h); /* fallback */ + } else { + int i; + + for(i = 0; i < arrlen(top->resize_queue); i++) { + if(top->resize_queue[i] == h) break; + } + if(i == arrlen(top->resize_queue)) arrput(top->resize_queue, h); + } +#else + RESIZE(h); +#endif } static void llclosehandler(MwLL handle, void* data) { @@ -112,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; @@ -124,6 +158,7 @@ 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; MwDispatch3(h, key, key); MwDispatchUserHandler(h, MwNkeyHandler, data); @@ -131,29 +166,40 @@ 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; MwDispatchUserHandler(h, MwNkeyReleaseHandler, data); } static void llfocusinhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; + if(MwGetInteger(h, MwNdisabled) == 1) return; MwDispatchUserHandler(h, MwNfocusInHandler, data); } static void llfocusouthandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; + if(MwGetInteger(h, MwNdisabled) == 1) return; MwDispatchUserHandler(h, MwNfocusOutHandler, data); } static void llclipboardhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; + if(MwGetInteger(h, MwNdisabled) == 1) return; MwDispatch3(h, clipboard, data); MwDispatchUserHandler(h, MwNclipboardHandler, data); } +static void lldraganddrophandler(MwLL handle, void* data) { + MwWidget h = (MwWidget)handle->common.user; + if(MwGetInteger(h, MwNdisabled) == 1) return; + + MwDispatchUserHandler(h, MwNdragAndDropHandler, data); +} + /* if both of them are true * 1. widget class is not NULL * 2. parent is NULL @@ -187,14 +233,19 @@ static void lldarkthemehandler(MwLL handle, void* data) { static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height, int do_prop, va_list prop) { MwWidget h = malloc(sizeof(*h)); - h->name = MwStringDuplicate(name); + if(name) + h->name = MwStringDuplicate(name); + else + h->name = NULL; h->parent = parent; h->children = NULL; if(widget_class != NULL) { if((h->lowlevel = MwLLCreate(parent == NULL ? NULL : parent->lowlevel, x, y, width, height)) == NULL) { - free(h->name); + if(h->name) { + free(h->name); + } free(h); return NULL; } @@ -219,27 +270,30 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, h->opaque = NULL; h->user = NULL; - h->top_step = 0; - h->draw_queue = NULL; + h->top_step = 0; + h->draw_queue = NULL; + h->resize_queue = NULL; + h->monitored_entries = NULL; if(parent == NULL) arrput(h->tick_list, h); 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.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); @@ -271,12 +325,21 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, MwAddTickList(h); } -#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) +#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); h->root_boldmonofont = MwFontLoad(MwBoldMonospaceTTFData, MwBoldMonospaceTTFDataSize); + if(!h->root_font) { +#ifdef USE_STB_TRUETYPE + MwFL_STBTTSetup(); + goto font_setup; +#endif + } } else #endif { @@ -365,7 +428,7 @@ void MwFreeWidget(MwWidget handle) { } } - free(handle->name); + if(handle->name) free(handle->name); if(handle->lowlevel != NULL) MwLLDestroy(handle->lowlevel); @@ -386,6 +449,7 @@ void MwFreeWidget(MwWidget handle) { arrfree(handle->tick_list); arrfree(handle->draw_queue); + arrfree(handle->resize_queue); if(handle->root_font != NULL) MwFontFree(handle->root_font); if(handle->root_boldfont != NULL) MwFontFree(handle->root_boldfont); @@ -465,7 +529,17 @@ static void MwAfterStep(MwWidget handle) { } #endif - if(arrlen(handle->tick_list) > 0 && (MwTimeGetTick() - handle->last_tick) >= MwWaitMS) { +#ifdef RESIZE_ON_TICK + if(handle->top_step) { + for(i = 0; i < arrlen(handle->resize_queue); i++) { + RESIZE(handle->resize_queue[i]); + } + + arrfree(handle->resize_queue); + } +#endif + + if(arrlen(handle->tick_list) > 0 && (MwTimeGetTick() - handle->last_tick) >= (MwGetInteger(handle, MwNwaitMS) == MwDEFAULT ? MwWaitMS : MwGetInteger(handle, MwNwaitMS))) { for(i = 0; i < arrlen(handle->tick_list); i++) { MwDispatch(handle->tick_list[i], tick); MwDispatchUserHandler(handle->tick_list[i], MwNtickHandler, NULL); @@ -499,6 +573,7 @@ int MwStep(MwWidget handle) { MwFreeWidget(handle); return 1; } + return 0; } @@ -507,7 +582,7 @@ int MwPending(MwWidget handle) { for(i = 0; i < arrlen(handle->children); i++) { if(MwPending(handle->children[i])) return 1; } - return (arrlen(handle->tick_list) > 0 && (MwTimeGetTick() - handle->last_tick) >= MwWaitMS) || (arrlen(handle->destroy_queue) > 0) || (handle->widget_class == NULL ? 0 : MwLLPending(handle->lowlevel)); + return (arrlen(handle->tick_list) > 0 && (MwTimeGetTick() - handle->last_tick) >= (MwGetInteger(handle, MwNwaitMS) == MwDEFAULT ? MwWaitMS : MwGetInteger(handle, MwNwaitMS))) || (arrlen(handle->destroy_queue) > 0) || (handle->widget_class == NULL ? 0 : MwLLPending(handle->lowlevel)); } void MwLoop(MwWidget handle) { @@ -571,8 +646,12 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { arrfree(keys); MwDispatch3(handle, prop_change, key); + } + + if(handle->parent != NULL && handle->parent->prop_event) { if(handle->parent != NULL) MwDispatch4(handle->parent, children_prop_change, handle, key); } + if(strcmp(key, MwNforceInverted) == 0) { MwForceRender(handle); } @@ -591,6 +670,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) { @@ -616,8 +699,12 @@ void MwSetText(MwWidget handle, const char* key, const char* value) { arrfree(keys); MwDispatch3(handle, prop_change, key); + } + + if(handle->parent != NULL && handle->parent->prop_event) { if(handle->parent != NULL) MwDispatch4(handle->parent, children_prop_change, handle, key); } + if(strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0) { MwForceRender(handle); } @@ -644,6 +731,9 @@ void MwSetVoid(MwWidget handle, const char* key, void* value) { arrfree(keys); MwDispatch3(handle, prop_change, key); + } + + if(handle->parent != NULL && handle->parent->prop_event) { if(handle->parent != NULL) MwDispatch4(handle->parent, children_prop_change, handle, key); } } @@ -671,7 +761,7 @@ int MwGetInteger(MwWidget handle, const char* key) { return MwDEFAULT; } else { if(shgeti(handle->integer, key) == -1) { -#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) +#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT) if(strcmp(key, MwNbitmapFont) == 0) return inherit_integer(handle, key, 0); #else if(strcmp(key, MwNbitmapFont) == 0) return inherit_integer(handle, key, 1); @@ -683,6 +773,7 @@ int MwGetInteger(MwWidget handle, const char* key) { #endif if(strcmp(key, MwNdarkTheme) == 0) return inherit_integer(handle, key, 0); if(strcmp(key, MwNuseMonospace) == 0) return inherit_integer(handle, key, 0); + if(strcmp(key, MwNdisabled) == 0) return inherit_integer(handle, key, 0); } return shget(handle->integer, key); } @@ -721,7 +812,7 @@ const char* MwGetText(MwWidget handle, const char* key) { return shget(handle->text, key); } -#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) +#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT) static void* inherit_void(MwWidget handle, const char* key) { void* v; @@ -737,7 +828,7 @@ void* MwGetVoid(MwWidget handle, const char* key) { if(v != NULL) return v; -#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) +#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT) if(strcmp(key, MwNfont) == 0 || strcmp(key, MwNboldFont) == 0 || strcmp(key, MwNmonospaceFont) == 0 || strcmp(key, MwNboldMonospaceFont) == 0) { v = inherit_void(handle, key); @@ -978,7 +1069,7 @@ typedef int (*call_t)(void); int MwLibraryInit(void) { call_t calls[] = { #ifdef USE_WAYLAND - MwLLWaylandCallInit, + NULL, /* set in a bit */ #endif #ifdef USE_X11 MwLLX11CallInit, @@ -998,6 +1089,29 @@ int MwLibraryInit(void) { NULL}; 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_PFN_timeBeginPeriod(10); +#endif + +#ifdef USE_WAYLAND + if(MwWaylandCairoOnly) { + calls[0] = MwLLCairoCallInit; + } else { + calls[0] = MwLLWaylandCallInit; + } +#endif + + MwColorTableInit(); + MwFLSetup(); for(i = 0; calls[i] != NULL; i++) { @@ -1055,8 +1169,10 @@ void MwReparent(MwWidget handle, MwWidget new_parent) { if(new_parent == NULL) { handle->top_step = 1; + arrput(handle->tick_list, handle); } else { handle->top_step = 0; + arrfree(handle->tick_list); } MwForceRender(handle); 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/dialog/messagebox.c b/src/dialog/messagebox.c index f7084ab..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; - unsigned int* data = NULL; + MwWidget icon; + MwLLPixmap px; + MwU32* data = NULL; icon = MwCreateWidget(MwImageClass, "image", window, 8, (h - 48) / 2, 48, 48); diff --git a/src/draw.c b/src/draw.c index 4d419bc..2314c02 100644 --- a/src/draw.c +++ b/src/draw.c @@ -38,6 +38,21 @@ static int hex(const char* txt, int len) { return r; } +static void color_set_disabled_if_disabled(MwWidget handle, MwLLColor rgb) { + if(MwGetInteger(handle, MwNdisabled) == 1) { + MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + + if(c != NULL) { + 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); + } + } +}; + void MwParseColorNoAllocate(const char* text, MwRGB* rgb) { if(text[0] == '#' && strlen(text) == 4) { rgb->red = hex(text + 1, 1); @@ -109,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; @@ -123,8 +141,9 @@ 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; data[idx + 1] = col->common.green; data[idx + 2] = col->common.blue; @@ -203,13 +222,15 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert if(rect->width <= 0 || rect->height <= 0) return; - col = invert ? MwLightenColor(handle, color, -8, -8, -8) : color; + col = invert ? MwLightenColor(handle, color, -8, -8, -8) : MwLightenColor(handle, color, 0, 0, 0); + color_set_disabled_if_disabled(handle, col); + if(MwGetInteger(handle, MwNmodernLook)) { MwDrawRectFading(handle, rect, col); } else { MwDrawRect(handle, rect, col); } - if(col != color) MwLLFreeColor(col); + MwLLFreeColor(col); } void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { @@ -218,7 +239,10 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { int ColorDiff = get_color_diff(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) : color; + MwLLColor col = invert ? MwLightenColor(handle, color, -8, -8, -8) : MwLightenColor(handle, color, 0, 0, 0); + color_set_disabled_if_disabled(handle, col); + color_set_disabled_if_disabled(handle, darker); + color_set_disabled_if_disabled(handle, lighter); p[0].x = rect->x; p[0].y = rect->y + rect->height / 2; @@ -274,7 +298,7 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { MwLLPolygon(handle->lowlevel, p, 4, col); - if(col != color) MwLLFreeColor(col); + MwLLFreeColor(col); MwLLFreeColor(lighter); MwLLFreeColor(darker); } @@ -284,8 +308,11 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, int ColorDiff = get_color_diff(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); - p[0].x = rect->x; - p[0].y = rect->y; + color_set_disabled_if_disabled(handle, darker); + color_set_disabled_if_disabled(handle, lighter); + + p[0].x = rect->x; + p[0].y = rect->y; p[1].x = rect->x + rect->width; p[1].y = rect->y; @@ -380,6 +407,9 @@ static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff); MwRect r = *rect; + 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); if(border > 1) { @@ -415,11 +445,14 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int ColorDiff = get_color_diff(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) : color; + MwLLColor col = invert ? MwLightenColor(handle, color, -8, -8, -8) : MwLightenColor(handle, color, 0, 0, 0); + double deg = 30 * ((direction == MwEAST || direction == MwWEST) ? 2 : 1); + double c = cos(deg / 180 * M_PI); + double s = sin(deg / 180 * M_PI); - double deg = 30 * ((direction == MwEAST || direction == MwWEST) ? 2 : 1); - double c = cos(deg / 180 * M_PI); - double s = sin(deg / 180 * M_PI); + color_set_disabled_if_disabled(handle, col); + color_set_disabled_if_disabled(handle, darker); + color_set_disabled_if_disabled(handle, lighter); if(direction == MwNORTH) { p1[0].x = rect->x + rect->width / 2; @@ -428,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; @@ -440,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; @@ -455,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; @@ -486,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; @@ -502,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; @@ -538,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; @@ -553,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; @@ -584,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; @@ -596,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; @@ -609,19 +642,18 @@ 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); - if(color != col) MwLLFreeColor(col); - + MwLLFreeColor(col); MwLLFreeColor(lighter); MwLLFreeColor(darker); } @@ -801,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; } } @@ -839,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++) { @@ -876,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]; @@ -913,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++) { diff --git a/src/lowlevel.c b/src/lowlevel.c index bc9e55b..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; @@ -50,8 +56,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; 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/font/boldmonottf.c b/src/text/font/boldmonottf.c index 7945831..8526c1b 100644 --- a/src/text/font/boldmonottf.c +++ b/src/text/font/boldmonottf.c @@ -1,6 +1,6 @@ #include -#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) +#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT) unsigned char MwBoldMonospaceTTFData[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x46, 0x46, 0x54, 0x4d, 0xac, 0x0d, 0xe4, 0x44, 0x00, 0x00, 0x8d, 0x3c, diff --git a/src/text/font/boldttf.c b/src/text/font/boldttf.c index 14b2599..2ec91c7 100644 --- a/src/text/font/boldttf.c +++ b/src/text/font/boldttf.c @@ -1,6 +1,6 @@ #include -#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) +#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT) unsigned char MwBoldTTFData[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, 0x04, 0x00, 0x20, 0x46, 0x46, 0x54, 0x4d, 0x94, 0x9f, 0x60, 0x18, 0x00, 0x00, 0x8e, 0xa8, diff --git a/src/text/font/monottf.c b/src/text/font/monottf.c index 8332c4a..7a89f94 100644 --- a/src/text/font/monottf.c +++ b/src/text/font/monottf.c @@ -1,6 +1,6 @@ #include -#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) +#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT) unsigned char MwMonospaceTTFData[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x46, 0x46, 0x54, 0x4d, 0xac, 0x0d, 0xe4, 0x23, 0x00, 0x00, 0x8d, 0x3c, diff --git a/src/text/font/ttf.c b/src/text/font/ttf.c index c5d03b9..7eeea07 100644 --- a/src/text/font/ttf.c +++ b/src/text/font/ttf.c @@ -1,6 +1,6 @@ #include -#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) +#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT) unsigned char MwTTFData[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, 0x04, 0x00, 0x20, 0x46, 0x46, 0x54, 0x4d, 0x94, 0x92, 0x79, 0xd4, 0x00, 0x00, 0x89, 0xa4, diff --git a/src/text/ft2.c b/src/text/ft2.c index b83b06c..13e8208 100644 --- a/src/text/ft2.c +++ b/src/text/ft2.c @@ -159,7 +159,7 @@ static void ft2_MwFontFree(void* handle) { free(ttf); } -int MWFL_FT2Setup(void) { +int MwFL_FT2Setup(void) { /* Try and load FreeType2. If it fails, return 1, signifying we default to stbtt. */ void* ftlib; #ifdef __APPLE__ diff --git a/src/text/gdi.c b/src/text/gdi.c new file mode 100644 index 0000000..97e6870 --- /dev/null +++ b/src/text/gdi.c @@ -0,0 +1,268 @@ +#ifdef USE_GDI_TEXT +#include + +static HANDLE(WINAPI* _AddFontMemResourceEx)(PVOID pFileView, DWORD cjSize, PVOID pvResrved, DWORD* pNumFonts) = NULL; +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); + +struct _MwFLFont { + HANDLE handle; + HFONT font; + HDC dc; +}; + +static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwLLColor color) { + BITMAPINFOHEADER bmih; + int tw; + int th; + HBITMAP hbm; + RGBQUAD* bits = NULL; + HDC hmdc; + char* t = MwUTF8ToACP(text); + unsigned char* px; + int y, x; + MwRect r; + MwLLPixmap p; + + tw = MwTextWidth(handle, ttf, text); + th = MwTextHeight(handle, ttf, text); + + 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, RGB(color->common.red, color->common.green, color->common.blue)); + + TextOut(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t, strlen(t)); + + 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; + } + + px = malloc(tw * th * 4); + + bmih.biSize = sizeof(bmih); + bmih.biWidth = tw; + bmih.biHeight = -(LONG)th; + bmih.biPlanes = 1; + bmih.biBitCount = 32; + bmih.biCompression = BI_RGB; + bmih.biSizeImage = 0; + bmih.biXPelsPerMeter = 0; + bmih.biYPelsPerMeter = 0; + bmih.biClrUsed = 0; + bmih.biClrImportant = 0; + + hbm = CreateDIBSection(ttf->dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + + hmdc = CreateCompatibleDC(ttf->dc); + SelectObject(hmdc, hbm); + SelectObject(hmdc, ttf->font); + + TextOut(hmdc, 0, 0, t, strlen(t)); + + DeleteDC(hmdc); + + for(y = 0; y < th; y++) { + for(x = 0; x < tw; x++) { + unsigned char* opx = &px[(y * tw + x) * 4]; + + opx[0] = color->common.red; + opx[1] = color->common.green; + opx[2] = color->common.blue; + opx[3] = 255 - bits[y * tw + x].rgbRed; + } + } + + p = MwLoadRaw(handle, px, tw, th); + r.x = point->x; + r.y = point->y - th / 2; + r.width = tw; + r.height = th; + + MwLLDrawPixmap(handle->lowlevel, &r, p); + MwLLDestroyPixmap(p); + free(px); + + DeleteObject(hbm); + free(t); + + return 0; +} + +static int GDI_MwTextWidth(MwFLFont ttf, const char* text) { + char* t = MwUTF8ToACP(text); + SIZE sz; + + GetTextExtentPoint32(ttf->dc, t, strlen(t), &sz); + + free(t); + + return sz.cx; +} + +static int GDI_MwTextHeight(MwFLFont ttf, int count) { + TEXTMETRIC tm; + + GetTextMetrics(ttf->dc, &tm); + + return tm.tmHeight * count; +} + +static void* GDI_MwFontLoad(unsigned char* data, unsigned int size, int px) { + MwFLFont ttf = malloc(sizeof(*ttf)); + DWORD c; + MwTTFInfo info; + + if((info = MwTTFGetInfo(data, size)) == NULL) { + free(ttf); + return NULL; + } + + ttf->dc = GetDC(NULL); + + ttf->handle = NULL; + + if(_AddFontMemResourceEx) { + if((ttf->handle = _AddFontMemResourceEx(data, size, 0, &c)) == NULL) { + ReleaseDC(NULL, ttf->dc); + MwTTFFreeInfo(info); + free(ttf); + return NULL; + } + } /*else { + if((ttf->handle = _AddFontMemResourceExPolyFill(data, size, 0, &c)) == NULL) { + ReleaseDC(NULL, ttf->dc); + MwTTFFreeInfo(info); + free(ttf); + return NULL; + } + }*/ + + if((ttf->font = CreateFont(-px, 0, 0, 0, info->weight, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, ttf->handle ? info->family : "Sans Serif")) == NULL) { + if(_RemoveFontMemResourceEx) { + _RemoveFontMemResourceEx(ttf->handle); + } else { + _RemoveFontMemResourceExPolyFill(ttf->handle); + } + ReleaseDC(NULL, ttf->dc); + MwTTFFreeInfo(info); + free(ttf); + return NULL; + } + + MwTTFFreeInfo(info); + + SelectObject(ttf->dc, ttf->font); + + return ttf; +} + +static void GDI_MwFontFree(void* handle) { + MwFLFont ttf = handle; + + DeleteObject(ttf->font); + if(_RemoveFontMemResourceEx) { + _RemoveFontMemResourceEx(ttf->handle); + } else { + _RemoveFontMemResourceExPolyFill(ttf->handle); + } + ReleaseDC(NULL, ttf->dc); + free(ttf); +} + +static HANDLE WINAPI _AddFontMemResourceExPolyFill(PVOID pFileView, DWORD cjSize, PVOID pvResrved, DWORD* pNumFonts) { + CHAR temp_path_dir[MAX_PATH]; + CHAR temp_path_name[MAX_PATH]; + HANDLE tempFile = NULL; + DWORD hr; + + (void)pvResrved; + + hr = GetTempPathA(MAX_PATH, temp_path_dir); + if(hr == 0) { + printf("GetTempPathA error %08lX\n", hr); + return NULL; + } + hr = GetTempFileNameA(temp_path_dir, TEXT("MILSKO"), 0, temp_path_name); + if(hr == 0) { + printf("GetTempFileNameA error %08lX\n", hr); + return NULL; + } + + printf("extracting mem font to %s\n", temp_path_name); + + tempFile = CreateFileA(temp_path_name, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + + if(tempFile == INVALID_HANDLE_VALUE) { + DWORD err = GetLastError(); + if(err == ERROR_ALREADY_EXISTS) { + tempFile = CreateFileA(temp_path_name, + GENERIC_WRITE, + 0, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + if(tempFile != INVALID_HANDLE_VALUE) { + goto success; + } else { + err = GetLastError(); + } + } + printf("CreateFileA error %08lX\n", err); + return NULL; + } + +success: + hr = WriteFile(tempFile, pFileView, cjSize, NULL, NULL); + if(hr != 0) { + printf("WriteFile error %08lX\n", hr); + return NULL; + } + + *pNumFonts = AddFontResource(temp_path_name); + + return tempFile; +}; +static BOOL WINAPI _RemoveFontMemResourceExPolyFill(HANDLE h) { + if(h) + CloseHandle(h); + return TRUE; +}; + +int MwFL_GDISetup(void) { + void* gdilib = LoadLibrary("gdi32.dll"); + if(!gdilib) { + printf("gdi32.dll not found(what)\n"); + } else { + _AddFontMemResourceEx = (void*)GetProcAddress(gdilib, "AddFontMemResourceEx"); + if(!_AddFontMemResourceEx) { + _AddFontMemResourceEx = _AddFontMemResourceExPolyFill; + } + _RemoveFontMemResourceEx = (void*)GetProcAddress(gdilib, "RemoveFontMemResourceEx"); + if(!_RemoveFontMemResourceEx) { + _RemoveFontMemResourceEx = _RemoveFontMemResourceExPolyFill; + } + } + + MwFLDrawText = GDI_MwDrawText; + MwFLTextWidth = GDI_MwTextWidth; + MwFLTextHeight = GDI_MwTextHeight; + MwFLFontLoad = GDI_MwFontLoad; + MwFLFontFree = GDI_MwFontFree; + return 0; +} + +#endif diff --git a/src/text/text.c b/src/text/text.c index f2d83a2..2bb89b6 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -3,10 +3,11 @@ int (*MwFLDrawText)(MwWidget handle, MwFLFont font, MwPoint* point, const char* text, MwLLColor color) = NULL; int (*MwFLTextWidth)(MwFLFont font, const char* text) = NULL; int (*MwFLTextHeight)(MwFLFont font, int count) = NULL; +int (*MwFLTextHeightWithText)(MwFLFont ttf, const char* text) = NULL; void* (*MwFLFontLoad)(unsigned char* data, unsigned int size, int px) = NULL; void (*MwFLFontFree)(void* handle) = NULL; -#if defined(USE_FREETYPE2) || defined(USE_STB_TRUETYPE) +#if defined(USE_FREETYPE2) || defined(USE_STB_TRUETYPE) || defined(USE_GDI_TEXT) #define TTF #endif @@ -76,10 +77,25 @@ static MwFLFont assume_ttf(MwWidget handle, MwFLFont ttf) { #endif void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, int align, MwLLColor color) { - MwPoint p = *point; - char* input = (char*)text; - char* last = input; - int cp; + MwPoint p = *point; + char* input = (char*)text; + char* last = input; + int cp; + MwLLColor fadedColor = NULL; + + if(MwGetInteger(handle, MwNdisabled) == 1) { + MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + + if(c != NULL) { + fadedColor = MwLLAllocColor(handle->lowlevel, color->common.red, color->common.blue, color->common.green); + 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); + } + } #ifdef TTF if(ttf <= MwFLBuildFont(0xff) && !is_bitmap(handle, ttf)) ttf = assume_ttf(handle, ttf); @@ -94,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; @@ -122,9 +143,9 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, #ifdef TTF if(MwFLDrawText) - if(is_bitmap(handle, ttf) || ttf == NULL || MwFLDrawText(handle, ttf, &p, line, color)) + 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), color); + bitmap_MwDrawText(handle, &p, line, is_bold(handle, ttf), fadedColor ? fadedColor : color); p.y += MwTextHeight(handle, ttf, line); @@ -133,6 +154,10 @@ void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, last = input; } } + + if(fadedColor) { + MwLLFreeColor(fadedColor); + } } int MwTextWidth(MwWidget handle, MwFLFont ttf, const char* text) { @@ -157,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; @@ -202,6 +232,8 @@ int MwTextHeight(MwWidget handle, MwFLFont ttf, const char* text) { #ifdef TTF if(MwFLTextHeight) if(!MwGetInteger(handle, MwNbitmapFont) && ttf != NULL && (st = MwFLTextHeight(ttf, c)) != -1) return st; + if(MwFLTextHeightWithText) + if(!MwGetInteger(handle, MwNbitmapFont) && ttf != NULL && (st = MwFLTextHeightWithText(ttf, text)) != -1) return st; #endif return FontHeight * c; } @@ -228,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; @@ -279,8 +316,11 @@ static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, typedef int (*call_t)(void); void MwFLSetup(void) { call_t calls[] = { +#ifdef USE_GDI_TEXT + MwFL_GDISetup, +#endif #ifdef USE_FREETYPE2 - MWFL_FT2Setup, + MwFL_FT2Setup, #endif #ifdef USE_STB_TRUETYPE MwFL_STBTTSetup, diff --git a/src/truetype.c b/src/truetype.c new file mode 100644 index 0000000..4f2c819 --- /dev/null +++ b/src/truetype.c @@ -0,0 +1,142 @@ +#include + +#define REMAIN (size - (data - old)) + +MwTTFInfo MwTTFGetInfo(unsigned char* data, int size) { + unsigned short n = 0; + int i; + unsigned char* old = data; + MwTTFInfo info = malloc(sizeof(*info)); + + memset(info, 0, sizeof(*info)); + + if(size < 12) { + MwTTFFreeInfo(info); + return NULL; + } + n |= data[4 + 0]; + n = n << 8; + n |= data[4 + 1]; + + data += 12; + for(i = 0; REMAIN > 0 && i < n; i++) { + unsigned int offset = 0; + unsigned int length = 0; + int j; + + if(REMAIN < (4 + 4 + 4 + 4)) { + MwTTFFreeInfo(info); + return NULL; + } + + for(j = 0; j < 4; j++) { + offset = offset << 8; + offset |= data[4 + 4 + j]; + + length = length << 8; + length |= data[4 + 4 + 4 + j]; + } + + if(memcmp(data, "OS/2", 4) == 0) { + if(length >= 68) { + unsigned char* rev = data; + unsigned short us_weight = 0; + + data = old + offset; + if(REMAIN < 68) { + MwTTFFreeInfo(info); + return NULL; + } + + for(j = 0; j < 2; j++) { + us_weight = us_weight << 8; + us_weight |= data[0x4 + j]; + } + + info->weight = us_weight; + + data = rev; + } + } else if(memcmp(data, "name", 4) == 0) { + if(length >= 6) { + unsigned short count = 0; + unsigned char* rev = data; + unsigned short str_off = 0; + unsigned char* beg; + + data = old + offset; + if(REMAIN < (2 + 2 + 2)) { + MwTTFFreeInfo(info); + return NULL; + } + + beg = data; + + for(j = 0; j < 2; j++) { + count = count << 8; + count |= data[2 + j]; + + str_off = str_off << 8; + str_off |= data[2 + 2 + j]; + } + + data += 2 + 2 + 2; + for(j = 0; j < count; j++) { + unsigned short platform = 0; + unsigned short name = 0; + unsigned short nam_len = 0; + unsigned short nam_off = 0; + int k; + + if(REMAIN < (2 + 2 + 2 + 2 + 2 + 2)) { + MwTTFFreeInfo(info); + return NULL; + } + + for(k = 0; k < 2; k++) { + platform = platform << 8; + platform |= data[0 + k]; + + name = name << 8; + name |= data[2 + 2 + 2 + k]; + + nam_len = nam_len << 8; + nam_len |= data[2 + 2 + 2 + 2 + k]; + + nam_off = nam_off << 8; + nam_off |= data[2 + 2 + 2 + 2 + 2 + k]; + } + + /* FIXME: this does not work with surrogate */ + if((platform == 0 || platform == 3) && name == 1) { + data = beg + str_off + nam_off; + if(REMAIN < nam_len) { + MwTTFFreeInfo(info); + return NULL; + } + + if(info->family != NULL) free(info->family); + + info->family = malloc(nam_len / 2 + 1); + + for(k = 0; k < nam_len / 2; k++) info->family[k] = data[k * 2 + 1]; + info->family[k] = 0; + } + + data += 2 + 2 + 2 + 2 + 2 + 2; + } + + data = rev; + } + } + + data += 4 + 4 + 4 + 4; + } + + return info; +} + +void MwTTFFreeInfo(MwTTFInfo info) { + if(info->family != NULL) free(info->family); + free(info); +} diff --git a/src/widget/box.c b/src/widget/box.c index 87807f4..00b5723 100644 --- a/src/widget/box.c +++ b/src/widget/box.c @@ -120,11 +120,11 @@ static void resize(MwWidget handle) { MwForceRender(handle); } -static void children_update(MwWidget handle, MwWidget child, int new) { +static void children_update(MwWidget handle, MwWidget child, int new_child) { MwBox b = handle->internal; (void)child; - (void)new; + (void)new_child; b->layout = 1; 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/entry.c b/src/widget/entry.c index 8580768..9d423bf 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -1,12 +1,19 @@ #include +#include "../../external/stb_ds.h" static int wcreate(MwWidget handle) { - MwEntry t = malloc(sizeof(*t)); + MwEntry t = malloc(sizeof(*t)); + MwWidget topmost_parent = handle->parent; - t->cursor = 0; - t->right = 0; - t->length = 0; - handle->internal = t; + t->cursor = 0; + 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; + arrpush(topmost_parent->monitored_entries, handle); MwSetDefault(handle); @@ -16,9 +23,27 @@ static int wcreate(MwWidget handle) { } static void destroy(MwWidget handle) { + int i; + MwWidget topmost_parent = handle->parent; + + while(topmost_parent->parent) topmost_parent = topmost_parent->parent; + for(i = 0; i < arrlen(topmost_parent->monitored_entries); i++) { + if(topmost_parent->monitored_entries[i] == handle) { + arrdel(topmost_parent->monitored_entries, i); + break; + } + } free(handle->internal); } - +static void tick(MwWidget handle) { + MwEntry t = handle->internal; + if(t->active) { + if(++t->cursor_blink_timer >= 30) { + t->cursor_blink_timer = 0; + } + MwForceRender(handle); + } +} static void draw(MwWidget handle) { MwRect r; MwEntry t = handle->internal; @@ -71,11 +96,13 @@ static void draw(MwWidget handle) { for(i = 0; i < textlen; i++) show[i] = 'M'; show[i] = 0; - currc.x = p.x + MwTextWidth(handle, font, show); - currc.y = (r.height - h) / 2 + MwDefaultBorderWidth(handle); - currc.width = 1; - currc.height = h; - MwDrawRect(handle, &currc, text); + if(t->active && t->cursor_blink_timer <= 15) { + currc.x = p.x + MwTextWidth(handle, font, show); + currc.y = (r.height - h) / 2 + MwDefaultBorderWidth(handle); + currc.width = 1; + currc.height = h; + MwDrawRect(handle, &currc, text); + } free(show); } @@ -148,6 +175,25 @@ static void mouse_up(MwWidget handle, void* ptr) { #define mouse_up MwForceRender2 #endif +static void mouse_down(MwWidget handle, void* ptr) { + int i = 0; + 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++) { + MwEntry t = topmost_parent->monitored_entries[i]->internal; + t->active = MwFALSE; + t->cursor_blink_timer = 0; + MwForceRender(topmost_parent->monitored_entries[i]); + } + t->active = MwTRUE; + MwForceRender2(handle, NULL); +} + static void prop_change(MwWidget handle, const char* prop) { if(strcmp(prop, MwNtext) == 0 || strcmp(prop, MwNhideInput) == 0) MwForceRender(handle); @@ -187,23 +233,23 @@ static void clipboard(MwWidget handle, const char* data) { } MwClassRec MwEntryClassRec = { - wcreate, /* create */ - destroy, /* destroy */ - draw, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - prop_change, /* prop_change */ - NULL, /* mouse_move */ - mouse_up, /* mouse_up */ - MwForceRender2, /* mouse_down */ - key, /* key */ - NULL, /* execute */ - NULL, /* tick */ - NULL, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - clipboard, /* clipboard */ - NULL, /* props_change */ + wcreate, /* create */ + destroy, /* destroy */ + draw, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + mouse_up, /* mouse_up */ + mouse_down, /* mouse_down */ + key, /* key */ + NULL, /* execute */ + tick, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + clipboard, /* clipboard */ + NULL, /* props_change */ NULL, NULL, NULL}; diff --git a/src/widget/label.c b/src/widget/label.c index 84277b2..a0be9ca 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -319,8 +319,8 @@ static void draw_normal(MwWidget handle) { MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); MwLLColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); int align; - const char* str = MwGetText(handle, MwNtext); - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + const char* str = MwGetText(handle, MwNtext); + MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); if(str == NULL) str = ""; @@ -336,6 +336,7 @@ static void draw_normal(MwWidget handle) { r.width -= MwGetInteger(handle, MwNleftPadding); +#if 1 if(align == MwALIGNMENT_CENTER) { p.x = r.width / 2; } else if(align == MwALIGNMENT_BEGINNING) { @@ -343,6 +344,9 @@ static void draw_normal(MwWidget handle) { } else if(align == MwALIGNMENT_END) { p.x = r.width - MwTextWidth(handle, NULL, str) / 2; } +#else + p.x = 0; +#endif p.y = r.height / 2; p.x += MwGetInteger(handle, MwNleftPadding); diff --git a/src/widget/listbox.c b/src/widget/listbox.c index 72fa743..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; @@ -400,8 +410,8 @@ static void draw(MwWidget handle) { } static void prop_change(MwWidget handle, const char* prop) { + MwListBox lb = handle->internal; if(strcmp(prop, MwNleftPadding) == 0) { - MwListBox lb = handle->internal; MwForceRender(lb->frame); } if(strcmp(prop, MwNhasHeading) == 0) { diff --git a/src/widget/menu.c b/src/widget/menu.c index 7df61f2..8dd3d7a 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -24,6 +24,7 @@ static int wcreate(MwWidget handle) { m->wsub = NULL; m->sub = NULL; handle->internal = m; + handle->is_menu = MwTRUE; MwSetDefault(handle); diff --git a/src/widget/opengl.c b/src/widget/opengl.c index bd3532b..30a1cee 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -239,7 +239,7 @@ static int wcreate(MwWidget handle) { EGLDisplay display; waylandopengl_t* o = r = malloc(sizeof(*o)); int gbm_format = 0; - EGLConfig egl_configs[1024]; + EGLConfig egl_configs[1024]; memset(o, 0, sizeof(waylandopengl_t)); o->gllib = MwDynamicOpen("libEGL.so"); @@ -346,7 +346,7 @@ static int wcreate(MwWidget handle) { } else { if(gbm_format == GBM_FORMAT_ARGB8888) { o->egl_config = egl_configs[i]; - break; + break; } } } @@ -513,8 +513,8 @@ static void mwOpenGLSwapBufferImpl(MwWidget handle) { #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { waylandopengl_t* o = handle->internal; - struct gbm_bo* bo; - eglSwapInterval(o->egl_display, 0); + struct gbm_bo* bo; + eglSwapInterval(o->egl_display, 0); if(!eglSwapBuffers(o->egl_display, o->egl_surface)) { printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); } @@ -682,4 +682,4 @@ MWDECL MwClass MwOpenGLClass; MwClass MwOpenGLClass = NULL; #endif -#endif \ No newline at end of file +#endif 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/tab.c b/src/widget/tab.c index 11d5861..e5d2a3e 100644 --- a/src/widget/tab.c +++ b/src/widget/tab.c @@ -39,6 +39,23 @@ static int tab_height(MwWidget handle) { return MwTextHeight(handle, NULL, "M") + 10; } +static int icon_width(MwWidget handle, const char* text) { + MwTab t = handle->internal; + int i; + + for(i = 0; i < arrlen(t->names); i++) { + if(strcmp(t->names[i], text) == 0) { + MwLLPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); + + if(px == NULL) return 0; + + return px->common.width * tab_height(handle) / px->common.height; + } + } + + return 0; +} + static void draw(MwWidget handle) { MwTab t = handle->internal; MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); @@ -60,6 +77,7 @@ static void draw(MwWidget handle) { x = 0; for(i = 0; i < arrlen(t->names); i++) { int render = 0; + int iw = icon_width(handle, t->names[i]); if(i == MwGetInteger(handle, MwNvalue) && n == 1) { r.y += h; @@ -73,11 +91,26 @@ static void draw(MwWidget handle) { r2.x = x; r2.y = 0; - r2.width = tab_width(handle, t->names[i]); + r2.width = tab_width(handle, t->names[i]) + iw; r2.height = tab_height(handle) + MwDefaultBorderWidth(handle); x += r2.width; + if(iw > 0) { + MwLLPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); + MwRect rp; + + rp = r2; + + rp.x += 5; + rp.y += 5; + + rp.width = iw - 10; + rp.height = rp.height * (iw - 10) / iw; + + MwLLDrawPixmap(handle->lowlevel, &rp, px); + } + if(render) { MwPoint p; @@ -151,7 +184,7 @@ static void draw(MwWidget handle) { MwDrawRect(handle, &r3, c); } - p.x = r2.x + r2.width / 2; + p.x = r2.x + (r2.width + iw / 2) / 2; p.y = r2.y + r2.height / 2; MwDrawText(handle, NULL, &p, t->names[i], MwALIGNMENT_CENTER, ct); } @@ -177,7 +210,10 @@ static void click(MwWidget handle) { int h = tab_height(handle); for(i = 0; i < arrlen(t->names); i++) { - int w = tab_width(handle, t->names[i]); + int w = tab_width(handle, t->names[i]); + int iw = icon_width(handle, t->names[i]); + + w += iw; if(MwGetInteger(handle, MwNvalue) != i && x <= handle->mouse_point.x && handle->mouse_point.x <= (x + w) && 0 <= handle->mouse_point.y && handle->mouse_point.y <= h) { MwSetInteger(handle, MwNvalue, i); @@ -188,9 +224,15 @@ static void click(MwWidget handle) { } } +static void prop_change(MwWidget handle, const char* key) { + if(strcmp(key, MwNvalue) == 0) { + show_frame(handle); + } +} + static MwWidget mwTabAddImpl(MwWidget handle, const char* name) { MwTab t = handle->internal; - MwWidget f = MwCreateWidget(MwFrameClass, "tabframe", handle, 0, MwGetInteger(handle, MwNheight), MwGetInteger(handle, MwNwidth) - MwDefaultBorderWidth(handle) * 2, MwGetInteger(handle, MwNheight) - tab_height(handle) - MwDefaultBorderWidth(handle) * 2); + MwWidget f = MwCreateWidget(MwFrameClass, "tabframe", handle, MwDefaultBorderWidth(handle), tab_height(handle) + MwDefaultBorderWidth(handle), MwGetInteger(handle, MwNwidth) - MwDefaultBorderWidth(handle) * 2, MwGetInteger(handle, MwNheight) - tab_height(handle) - MwDefaultBorderWidth(handle) * 2); char* n = MwStringDuplicate(name); arrput(t->frames, f); @@ -201,6 +243,8 @@ static MwWidget mwTabAddImpl(MwWidget handle, const char* name) { if(MwGetInteger(handle, MwNvalue) == -1) { MwSetInteger(handle, MwNvalue, arrlen(t->frames) - 1); show_frame(handle); + } else { + MwLLShow(f->lowlevel, 0); } return f; @@ -217,6 +261,19 @@ static MwWidget mwTabGetFrameImpl(MwWidget handle, const char* name) { return NULL; } +static void mwTabFocusImpl(MwWidget handle, const char* name) { + MwTab t = handle->internal; + int i; + + for(i = 0; i < arrlen(t->names); i++) { + if(strcmp(t->names[i], name) == 0) { + MwSetInteger(handle, MwNvalue, i); + show_frame(handle); + break; + } + } +} + static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { if(strcmp(name, "mwTabAdd") == 0) { const char* name = va_arg(va, const char*); @@ -226,6 +283,10 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v const char* name = va_arg(va, const char*); *(MwWidget*)out = mwTabGetFrameImpl(handle, name); + } else if(strcmp(name, "mwTabFocus") == 0) { + const char* name = va_arg(va, const char*); + + mwTabFocusImpl(handle, name); } } @@ -237,6 +298,7 @@ static void resize(MwWidget handle) { for(i = 0; i < arrlen(t->frames); i++) { int y = MwGetInteger(handle, MwNheight); + MwLLShow(t->frames[i]->lowlevel, i == v); if(i == v) y = tab_height(handle) + MwDefaultBorderWidth(handle); MwVaApply(t->frames[i], @@ -248,24 +310,65 @@ static void resize(MwWidget handle) { } } +static void children_update(MwWidget handle, MwWidget child, int new_child) { + MwTab t = handle->internal; + int v = MwGetInteger(handle, MwNvalue); + int n; + int i; + + if(new_child) return; + + for(i = 0; i < arrlen(t->frames); i++) { + if(t->frames[i] == child) { + n = i; + break; + } + } + + free(t->names[n]); + + arrdel(t->frames, n); + arrdel(t->names, n); + + if(n <= v) { + if(v > 0) v--; + + MwSetInteger(handle, MwNvalue, v); + show_frame(handle); + } else { + MwSetInteger(handle, MwNvalue, v); + show_frame(handle); + } + + MwForceRender(handle); +} + +static void children_prop_change(MwWidget handle, MwWidget child, const char* key) { + (void)child; + + if(strcmp(key, MwNiconPixmap) == 0) { + MwForceRender(handle); + } +} + MwClassRec MwTabClassRec = { - wcreate, /* create */ - destroy, /* destroy */ - draw, /* draw */ - click, /* click */ - NULL, /* parent_resize */ - NULL, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler, /* execute */ - NULL, /* tick */ - resize, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ + wcreate, /* create */ + destroy, /* destroy */ + draw, /* draw */ + click, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler, /* execute */ + NULL, /* tick */ + resize, /* resize */ + children_update, /* children_update */ + children_prop_change, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ NULL, NULL, NULL}; diff --git a/src/widget/table.c b/src/widget/table.c index ecd778c..788d5cc 100644 --- a/src/widget/table.c +++ b/src/widget/table.c @@ -170,11 +170,11 @@ static void resize(MwWidget handle) { MwForceRender(handle); } -static void children_update(MwWidget handle, MwWidget child, int new) { +static void children_update(MwWidget handle, MwWidget child, int new_child) { MwTable t = handle->internal; t->layout = 1; - if(new) { + if(new_child) { arrput(t->widgets, child); } else { int i; 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, diff --git a/src/widget/window.c b/src/widget/window.c index 7178d3f..3d0afe2 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -35,6 +35,10 @@ static void mwWindowMakeBorderlessImpl(MwWidget handle, int toggle) { MwLLEndStateChange(handle->lowlevel); } +static void mwWindowShouldCloseImpl(MwWidget handle, MwBool* out) { + *out = handle->close; +} + static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { (void)out; @@ -42,6 +46,10 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v int toggle = va_arg(va, int); mwWindowMakeBorderlessImpl(handle, toggle); } + if(strcmp(name, "mwWindowShouldClose") == 0) { + MwBool* out = va_arg(va, MwBool*); + mwWindowShouldCloseImpl(handle, out); + } } MwClassRec MwWindowClassRec = { wcreate, /* create */ diff --git a/tools/color.pl b/tools/color.pl index e872ead..eca072c 100755 --- a/tools/color.pl +++ b/tools/color.pl @@ -4,6 +4,15 @@ open(OUT, ">", "src/color.c"); print(OUT "#include \n"); print(OUT "\n"); +print(OUT "#include \"../external/stb_ds.h\"\n"); +print(OUT "\n"); +print(OUT "struct color {\n"); +print(OUT " char* key;\n"); +print(OUT " MwU32 value;\n"); +print(OUT "};\n"); +print(OUT "\n"); +print(OUT "static struct color* colors = NULL;\n"); +print(OUT "\n"); print(OUT "MwLLColor MwParseColorName(MwWidget handle, const char* color){\n"); print(OUT " MwRGB rgb;\n"); print(OUT " MwParseColorNameNoAllocate(color, &rgb);\n"); @@ -13,21 +22,29 @@ print(OUT print(OUT "}\n"); print(OUT "\n"); print(OUT "void MwParseColorNameNoAllocate(const char* color, MwRGB* rgb){\n"); +print(OUT " MwU32 v = shget(colors, color);"); +print(OUT " rgb->red = (v >> 16) & 0xff;"); +print(OUT " rgb->green = (v >> 8) & 0xff;"); +print(OUT " rgb->blue = (v >> 0) & 0xff;"); +print(OUT "}\n"); +print(OUT "\n"); +print(OUT + "static void add_color(const char* name, int red, int green, int blue){\n" +); +print(OUT " MwU32 v = (red << 16) | (green << 8) | (blue << 0);\n"); +print(OUT " shput(colors, name, v);\n"); +print(OUT "}\n"); +print(OUT "\n"); +print(OUT "void MwColorTableInit(void){\n"); +print(OUT " sh_new_strdup(colors);\n"); +print(OUT " shdefault(colors, 0);\n"); while (my $l = ) { $l =~ s/\r?\n$//; if ($l =~ /^[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]+(.+)$/) { - print(OUT " if(strcmp(color, \"$4\") == 0){\n"); - print(OUT " rgb->red = $1;\n"); - print(OUT " rgb->green = $2;\n"); - print(OUT " rgb->blue = $3;\n"); - print(OUT " return;\n"); - print(OUT " }\n"); + print(OUT " add_color(\"$4\", $1, $2, $3);\n"); } } -print(OUT " rgb->red = 0;\n"); -print(OUT " rgb->green = 0;\n"); -print(OUT " rgb->blue = 0;\n"); print(OUT "}\n"); close(OUT); diff --git a/tools/genmk.pl b/tools/genmk.pl index 6977df2..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_TRUETYPE ${def}USE_STB_IMAGE ${def}STBI_NO_SIMD\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"); @@ -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}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");