pax_global_header00006660000000000000000000000064151640257700014521gustar00rootroot0000000000000052 comment=0230c0dabb79b7317aa492be74141454144204c4 smooth-0.9.11~git20260403.0230c0da/000077500000000000000000000000001516402577000157605ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/.gitattributes000066400000000000000000000000101516402577000206420ustar00rootroot00000000000000* -text smooth-0.9.11~git20260403.0230c0da/.github/000077500000000000000000000000001516402577000173205ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/.github/workflows/000077500000000000000000000000001516402577000213555ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/.github/workflows/codeql-analysis.yml000066400000000000000000000035251516402577000251750ustar00rootroot00000000000000name: "Code scanning" on: push: branches: [ master ] pull_request: # The branches below must be a subset of the branches above branches: [ master ] schedule: - cron: '0 4 * * 2' jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ 'cpp' ] steps: # Install dependencies. - run: | sudo apt update sudo apt install -y libbz2-dev libcurl4-openssl-dev libfribidi-dev libgtk-3-dev libjpeg-dev libxml2-dev - name: Checkout repository uses: actions/checkout@v6 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 smooth-0.9.11~git20260403.0230c0da/.github/workflows/verify-build.yml000066400000000000000000000025441516402577000245060ustar00rootroot00000000000000name: "Verify build" on: push: pull_request: schedule: - cron: '0 6 * * 1' jobs: build: strategy: matrix: include: - os: ubuntu-latest cc: gcc cxx: g++ - os: ubuntu-latest cc: clang cxx: clang++ - os: macos-latest cc: clang cxx: clang++ - os: windows-latest cc: gcc cxx: g++ runs-on: ${{ matrix.os }} defaults: run: shell: bash steps: - name: Install dependencies if: ${{ runner.os == 'Linux' }} run: | sudo apt update sudo apt install -y libbz2-dev libcurl4-openssl-dev libfribidi-dev libgtk-3-dev libjpeg-dev libxml2-dev - name: Checkout repository uses: actions/checkout@v6 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. fetch-depth: 2 # If this run was triggered by a pull request event, then checkout # the head of the pull request instead of the merge commit. - run: git checkout HEAD^2 if: ${{ github.event_name == 'pull_request' }} - name: Build env: CC: ${{ matrix.cc }} CXX: ${{ matrix.cxx }} run: | make -j$(nproc) smooth-0.9.11~git20260403.0230c0da/.gitignore000066400000000000000000000004511516402577000177500ustar00rootroot00000000000000# Ignore artifacts created during build. BuildNumber *.[oa] *.so *.so.* *.dylib *.dll *.exe *.pyc bin/* bin64/* lib/* lib64/* libraries/v8/libraries.cc libraries/v8/experimental-libraries.cc msvc/**/.vs/* msvc/**/Debug/* msvc/**/Release/* msvc/**/*.VC.* msvc/**/*.vcxproj.user smooth-0.9.11~git20260403.0230c0da/ChangeLog000066400000000000000000000013561516402577000175370ustar00rootroot00000000000000ChangeLog for smooth dd.mm.yy hh:mm - smooth alpha 0.9.11 - bitmaphaiku.cpp - fixed bitmap transparency issues - filedlg_gtk.cpp - fixed GTK file dialog appearing in the background on X11 systems - timerposix.cpp - fixed potential deadlocks when using POSIX timers with GLib/GTK - fixed crash querying CPU info on systems without affinity setting support in libcpuid - fixed compilation with Xcode 16.3 and later toolchains - upgraded fribidi to version 1.0.16 - upgraded libcpuid to version 0.8.0 - upgraded libxml2 to version 2.15.1 - upgraded libcurl to version 8.11.0 - upgraded libiconv to version 1.19 - upgraded libpng to version 1.6.56 - upgraded libwebp to version 1.6.0 - upgraded zlib to version 1.3.2 - upgraded libjpeg to version 10 smooth-0.9.11~git20260403.0230c0da/Copying000066400000000000000000000216151516402577000173200ustar00rootroot00000000000000 The Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. Definitions "Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. "Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. "You" and "your" means any person who would like to copy, distribute, or modify the Package. "Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. "Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. "Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. "Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. "Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. "Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. "Source" form means the source code, documentation source, and configuration files for the Package. "Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. Permission for Use and Modification Without Distribution (1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. Permissions for Redistribution of the Standard Version (2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. (3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. Distribution of Modified Versions of the Package as Source (4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: (a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. (b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. (c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under (i) the Original License or (ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source (5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. (6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. Aggregating or Linking the Package (7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. (8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. Items That are Not Considered Part of a Modified Version (9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. General Provisions (10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. (11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. (12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. (13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.smooth-0.9.11~git20260403.0230c0da/Makefile000066400000000000000000000416121516402577000174240ustar00rootroot00000000000000# Makefile for smooth v0.9 SMOOTH_PATH = . include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options ### Object files ### OBJECTS = classes/backends/backend.o OBJECTS += classes/basic/object.o classes/basic/objecttype.o classes/basic/setup.o OBJECTS += classes/errors/error.o classes/errors/success.o OBJECTS += classes/errors/fs/endoffile.o classes/errors/fs/filenotfound.o OBJECTS += classes/errors/misc/permissiondenied.o OBJECTS += classes/files/directory.o classes/files/file.o OBJECTS += classes/graphics/bitmap.o classes/graphics/color.o classes/graphics/font.o classes/graphics/surface.o OBJECTS += classes/graphics/backends/bitmapbackend.o classes/graphics/backends/fontbackend.o classes/graphics/backends/surfacebackend.o OBJECTS += classes/graphics/forms/rect.o OBJECTS += classes/graphics/imageloader/imageloader.o classes/graphics/imageloader/jpeg.o classes/graphics/imageloader/pci.o classes/graphics/imageloader/png.o classes/graphics/imageloader/webp.o OBJECTS += classes/graphics/modifiers/fontsize.o classes/graphics/modifiers/righttoleft.o OBJECTS += classes/gui/application/application.o OBJECTS += classes/gui/clipboard/clipboard.o OBJECTS += classes/gui/clipboard/backends/clipboardbackend.o OBJECTS += classes/gui/dialogs/colordlg.o classes/gui/dialogs/dialog.o classes/gui/dialogs/fontdlg.o classes/gui/dialogs/messagebox.o classes/gui/dialogs/splashscreen.o classes/gui/dialogs/tipodaydlg.o OBJECTS += classes/gui/dialogs/directory/dirdlg.o OBJECTS += classes/gui/dialogs/file/filedlg.o OBJECTS += classes/gui/dialogs/icons/light.o OBJECTS += classes/gui/widgets/layer.o classes/gui/widgets/widget.o OBJECTS += classes/gui/widgets/basic/activearea.o classes/gui/widgets/basic/arrows.o classes/gui/widgets/basic/button.o classes/gui/widgets/basic/checkbox.o classes/gui/widgets/basic/client.o classes/gui/widgets/basic/divider.o classes/gui/widgets/basic/editbox.o classes/gui/widgets/basic/groupbox.o classes/gui/widgets/basic/hyperlink.o classes/gui/widgets/basic/image.o classes/gui/widgets/basic/multiedit.o classes/gui/widgets/basic/optionbox.o classes/gui/widgets/basic/progressbar.o classes/gui/widgets/basic/scrollbar.o classes/gui/widgets/basic/slider.o classes/gui/widgets/basic/statusbar.o classes/gui/widgets/basic/tabwidget.o classes/gui/widgets/basic/text.o classes/gui/widgets/basic/titlebar.o OBJECTS += classes/gui/widgets/hotspot/hotspot.o classes/gui/widgets/hotspot/simplebutton.o OBJECTS += classes/gui/widgets/multi/generic/container.o classes/gui/widgets/multi/generic/entry.o OBJECTS += classes/gui/widgets/multi/image/imagebox.o classes/gui/widgets/multi/image/imageentry.o OBJECTS += classes/gui/widgets/multi/list/combobox.o classes/gui/widgets/multi/list/list.o classes/gui/widgets/multi/list/listbox.o classes/gui/widgets/multi/list/listboxheader.o classes/gui/widgets/multi/list/listentry.o classes/gui/widgets/multi/list/listentryseparator.o OBJECTS += classes/gui/widgets/multi/menu/menu.o classes/gui/widgets/multi/menu/menubar.o classes/gui/widgets/multi/menu/menubarentry.o classes/gui/widgets/multi/menu/menuentry.o classes/gui/widgets/multi/menu/micromenu.o classes/gui/widgets/multi/menu/popupmenu.o classes/gui/widgets/multi/menu/popupmenuentry.o classes/gui/widgets/multi/menu/popupmenuentrycheck.o classes/gui/widgets/multi/menu/popupmenuentryoption.o OBJECTS += classes/gui/widgets/multi/tree/tree.o OBJECTS += classes/gui/widgets/special/cursor.o classes/gui/widgets/special/dragcontrol.o classes/gui/widgets/special/droparea.o classes/gui/widgets/special/shortcut.o classes/gui/widgets/special/tooltip.o OBJECTS += classes/gui/window/toolwindow.o classes/gui/window/window.o OBJECTS += classes/gui/window/backends/windowbackend.o OBJECTS += classes/i18n/language.o classes/i18n/number.o classes/i18n/section.o classes/i18n/translator.o classes/i18n/translator_internal.o OBJECTS += classes/input/keyboard.o classes/input/pointer.o OBJECTS += classes/input/backends/pointerbackend.o OBJECTS += classes/io/driver.o classes/io/filter.o classes/io/instream.o classes/io/outstream.o classes/io/stream.o OBJECTS += classes/io/drivers/driver_ansi.o classes/io/drivers/driver_https.o classes/io/drivers/driver_memory.o classes/io/drivers/driver_posix.o classes/io/drivers/driver_socket.o classes/io/drivers/driver_socks4.o classes/io/drivers/driver_socks5.o classes/io/drivers/driver_zero.o OBJECTS += classes/io/filters/filter_bzip2.o classes/io/filters/filter_xor.o OBJECTS += classes/misc/args.o classes/misc/array.o classes/misc/binary.o classes/misc/config.o classes/misc/datetime.o classes/misc/math.o classes/misc/memory.o classes/misc/number.o classes/misc/string.o classes/misc/string_case.o OBJECTS += classes/misc/encoding/base64.o classes/misc/encoding/urlencode.o OBJECTS += classes/misc/hash/crc16.o classes/misc/hash/crc32.o classes/misc/hash/crc64.o classes/misc/hash/md5.o classes/misc/hash/sha1.o OBJECTS += classes/net/protocols/file.o classes/net/protocols/http.o classes/net/protocols/protocol.o OBJECTS += classes/system/console.o classes/system/cpu.o classes/system/dynamicloader.o classes/system/event.o classes/system/screen.o classes/system/system.o classes/system/timer.o OBJECTS += classes/system/backends/eventbackend.o classes/system/backends/screenbackend.o classes/system/backends/timerbackend.o OBJECTS += classes/threads/access.o classes/threads/mutex.o classes/threads/rwlock.o classes/threads/semaphore.o classes/threads/thread.o OBJECTS += classes/threads/backends/mutexbackend.o classes/threads/backends/semaphorebackend.o classes/threads/backends/threadbackend.o OBJECTS += classes/xml/attribute.o classes/xml/document.o classes/xml/node.o OBJECTS += classes/xml/xul/box.o classes/xml/xul/button.o classes/xml/xul/description.o classes/xml/xul/label.o classes/xml/xul/menubar.o classes/xml/xul/popupmenu.o classes/xml/xul/renderer.o classes/xml/xul/textbox.o classes/xml/xul/widget.o classes/xml/xul/window.o OBJECTS += misc/codecs.o misc/init.o misc/pciio.o ifeq ($(BUILD_WIN32),True) OBJECTS += classes/backends/win32/backendwin32.o OBJECTS += classes/graphics/imageloader/icon.o OBJECTS += classes/gui/application/xulloader.o OBJECTS += classes/gui/clipboard/backends/win32/clipboardwin32.o OBJECTS += classes/gui/dialogs/directory/dirdlg_win32.o OBJECTS += classes/gui/dialogs/file/filedlg_win32.o OBJECTS += classes/gui/window/backends/gdi/droptarget.o classes/gui/window/backends/gdi/windowgdi.o OBJECTS += classes/input/backends/win32/pointerwin32.o OBJECTS += classes/io/drivers/driver_win32.o OBJECTS += classes/system/backends/win32/eventwin32.o classes/system/backends/win32/screenwin32.o classes/system/backends/win32/timerwin32.o OBJECTS += classes/threads/backends/win32/mutexwin32.o classes/threads/backends/win32/semaphorewin32.o classes/threads/backends/win32/threadwin32.o ifeq ($(BUILD_GDIPLUS),True) OBJECTS += classes/backends/gdiplus/backendgdiplus.o OBJECTS += classes/graphics/backends/gdiplus/bitmapgdiplus.o classes/graphics/backends/gdiplus/fontgdiplus.o classes/graphics/backends/gdiplus/surfacegdiplus.o else OBJECTS += classes/graphics/backends/gdi/bitmapgdi.o classes/graphics/backends/gdi/fontgdi.o classes/graphics/backends/gdi/surfacegdi.o endif else ifeq ($(BUILD_OSX),True) OBJECTS += classes/backends/cocoa/backendcocoa.o OBJECTS += classes/graphics/backends/cocoa/bitmapcocoa.o classes/graphics/backends/cocoa/fontcocoa.o classes/graphics/backends/cocoa/surfacecocoa.o OBJECTS += classes/gui/clipboard/backends/cocoa/clipboardcocoa.o OBJECTS += classes/gui/dialogs/directory/dirdlg_cocoa.o OBJECTS += classes/gui/dialogs/file/filedlg_cocoa.o OBJECTS += classes/gui/widgets/multi/menu/menubar_cocoa.o OBJECTS += classes/gui/window/backends/cocoa/windowcocoa.o OBJECTS += classes/input/backends/cocoa/pointercocoa.o OBJECTS += classes/system/backends/cocoa/eventcocoa.o classes/system/backends/cocoa/screencocoa.o classes/system/backends/cocoa/timercocoa.o else ifeq ($(BUILD_HAIKU),True) OBJECTS += classes/backends/haiku/backendhaiku.o OBJECTS += classes/graphics/backends/haiku/bitmaphaiku.o classes/graphics/backends/haiku/fonthaiku.o classes/graphics/backends/haiku/surfacehaiku.o OBJECTS += classes/gui/clipboard/backends/haiku/clipboardhaiku.o OBJECTS += classes/gui/dialogs/directory/dirdlg_haiku.o OBJECTS += classes/gui/dialogs/file/filedlg_haiku.o OBJECTS += classes/gui/window/backends/haiku/windowhaiku.o OBJECTS += classes/input/backends/haiku/pointerhaiku.o OBJECTS += classes/system/backends/haiku/eventhaiku.o classes/system/backends/haiku/screenhaiku.o classes/system/backends/haiku/timerhaiku.o else OBJECTS += classes/gui/dialogs/directory/dirdlg_gtk.o OBJECTS += classes/gui/dialogs/file/filedlg_gtk.o endif ifeq ($(BUILD_XLIB),True) OBJECTS += classes/backends/xlib/backendxlib.o OBJECTS += classes/graphics/backends/xlib/bitmapxlib.o OBJECTS += classes/gui/clipboard/backends/xlib/clipboardxlib.o OBJECTS += classes/gui/window/backends/xlib/windowxlib.o OBJECTS += classes/input/backends/xlib/pointerxlib.o OBJECTS += classes/system/backends/xlib/eventxlib.o classes/system/backends/xlib/screenxlib.o ifeq ($(BUILD_CAIRO),True) OBJECTS += classes/graphics/backends/cairo/fontcairo.o classes/graphics/backends/cairo/surfacecairo.o else OBJECTS += classes/graphics/backends/xlib/fontxlib.o classes/graphics/backends/xlib/surfacexlib.o endif endif ifeq ($(BUILD_POSIXTIMER),True) OBJECTS += classes/system/backends/posix/timerposix.o else ifeq ($(BUILD_THREADSTIMER),True) OBJECTS += classes/system/backends/threads/timerthreads.o endif ifeq ($(BUILD_POSIXTHREADS),True) OBJECTS += classes/threads/backends/posix/mutexposix.o classes/threads/backends/posix/semaphoreposix.o ifeq ($(BUILD_OSX),True) OBJECTS += classes/threads/backends/cocoa/threadcocoa.o else OBJECTS += classes/threads/backends/posix/threadposix.o endif endif ### Output options ### LIBS = ifeq ($(USE_BUNDLED_LIBBZ2),True) LIBS += $(LIBDIR)/libbz2.a else LIBS += -lbz2 endif ifeq ($(USE_BUNDLED_LIBCPUID),True) LIBS += $(LIBDIR)/libcpuid.a else LIBS += -lcpuid endif ifeq ($(USE_BUNDLED_LIBCURL),True) LIBS += $(LIBDIR)/libcurl.a ifeq ($(BUILD_WIN32),True) LIBS += -lwldap32 -lcrypt32 -lbcrypt else ifeq ($(BUILD_OSX),True) LIBS += -framework Security -lldap endif else ifeq ($(BUILD_OSX),True) LIBS += -lcurl else LIBS += $(shell pkg-config --libs libcurl) endif ifeq ($(USE_BUNDLED_LIBFRIBIDI),True) LIBS += $(LIBDIR)/libfribidi.a else LIBS += -lfribidi endif ifeq ($(USE_BUNDLED_LIBICONV),True) LIBS += $(LIBDIR)/libiconv.a else ifeq ($(BUILD_OSX),True) LIBS += -liconv else ifeq ($(BUILD_HAIKU),True) LIBS += -liconv endif ifeq ($(USE_BUNDLED_LIBJPEG),True) LIBS += $(LIBDIR)/libjpeg.a else LIBS += -ljpeg endif ifeq ($(USE_BUNDLED_LIBPNG),True) LIBS += $(LIBDIR)/libpng.a else ifeq ($(BUILD_WIN32),True) LIBS += -lpng else ifeq ($(BUILD_OSX),True) LIBS += -lpng else ifeq ($(BUILD_HAIKU),True) LIBS += -lpng else LIBS += $(shell pkg-config --libs libpng) endif ifeq ($(USE_BUNDLED_LIBWEBP),True) LIBS += $(LIBDIR)/libwebp.a else LIBS += $(shell pkg-config --libs libwebp) endif ifeq ($(USE_BUNDLED_LIBXML2),True) LIBS += $(LIBDIR)/libxml2.a else LIBS += -lxml2 endif ifeq ($(USE_BUNDLED_ZLIB),True) LIBS += $(LIBDIR)/libz.a else LIBS += -lz endif ifeq ($(BUILD_WIN32),True) OBJECTS += resources/resources.o ifneq ($(BUILD_GDIPLUS),True) LIBS += -lmsimg32 else LIBS += -lgdiplus endif LIBS += -lws2_32 -limm32 -lole32 -luuid DLLNAME = $(BINDIR)/smooth$(SHARED) LIBNAME = $(LIBDIR)/libsmooth.a else ifeq ($(BUILD_OSX),True) LIBS += -lpthread DLLNAME = $(LIBDIR)/libsmooth-$(VERSION)$(SHARED) else ifeq ($(BUILD_HAIKU),True) LIBS += -lbe -ltracker -lnetwork DLLNAME = $(LIBDIR)/libsmooth-$(VERSION)$(SHARED) else ifeq ($(BUILD_FREEBSD),True) LIBS += -lrt else ifeq ($(BUILD_LINUX),True) LIBS += -lrt else ifeq ($(BUILD_OPENBSD),True) LIBS += -lXau -lXdmcp -lXxf86vm -lSM -lICE -lffi -ldrm -lpcre endif ifneq ($(BUILD_CAIRO),True) LIBS += $(shell pkg-config --libs xft) endif LIBS += -lpthread LIBS += $(shell pkg-config --libs gtk+-x11-3.0) DLLNAME = $(LIBDIR)/libsmooth-$(VERSION)$(SHARED) endif ### Linker options ### REMOVE = rm LINKER_OPTS = -L$(LIBDIR) -o $(DLLNAME) REMOVE_OPTS = -f ifeq ($(BUILD_WIN32),True) LINKER_OPTS += --shared -mwindows -Wl,--dynamicbase,--nxcompat,--kill-at,--out-implib,$(LIBNAME) else ifeq ($(BUILD_OSX),True) LINKER_OPTS += -dynamiclib -framework Carbon -framework Cocoa -Wl,-dylib_install_name,libsmooth-$(VERSION).$(REVISION)$(SHARED) else LINKER_OPTS += --shared -Wl,-soname,libsmooth-$(VERSION)$(SHARED).$(REVISION) ifeq ($(BUILD_FREEBSD),True) LINKER_OPTS += -L/usr/local/lib else ifeq ($(BUILD_OPENBSD),True) LINKER_OPTS += -Wl,-rpath,/usr/local/lib -L/usr/local/lib -Wl,-rpath,/usr/X11R6/lib -L/usr/X11R6/lib else ifeq ($(BUILD_NETBSD),True) LINKER_OPTS += -Wl,-rpath,/usr/pkg/lib -L/usr/pkg/lib -Wl,-rpath,/usr/X11R7/lib -L/usr/X11R7/lib endif endif ### Install options ### COPY = cp LINK = ln CHMOD = chmod ### Targets ### .PHONY: all codesign folders objects lib programs libs install uninstall clean distclean doc doc-clean all: lib programs folders: mkdir -p $(SMOOTH_PATH)/$(BINDIR) $(SMOOTH_PATH)/$(LIBDIR) objects: + $(call makein,classes) + $(call makein,misc) + $(call makein,resources) lib: folders $(DLLNAME) programs: lib + $(call makein,tools) + $(call makein,samples) libs: + $(call makein,libraries) codesign: all signtool sign -fd sha1 -tr http://timestamp.digicert.com -td sha1 $(BINDIR)/smooth*.dll $(BINDIR)/translator.exe signtool sign -fd sha256 -tr http://timestamp.digicert.com -td sha256 -as $(BINDIR)/smooth*.dll $(BINDIR)/translator.exe install: all ifneq ($(BUILD_WIN32),True) $(INSTALL) -d "$(DESTDIR)"$(libdir) ifneq ($(BUILD_OSX),True) $(INSTALL_DATA) $(DLLNAME) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED).$(REVISION) $(LINK) -fs libsmooth-$(VERSION)$(SHARED).$(REVISION) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED) ifeq ($(BUILD_V8),True) $(INSTALL_DATA) $(LIBDIR)/libsmooth-js-$(VERSION)$(SHARED) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED).$(REVISION) $(LINK) -fs libsmooth-js-$(VERSION)$(SHARED).$(REVISION) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED) endif ifneq ($(BUILD_SOLARIS),True) ifneq ($(BUILD_HAIKU),True) ifeq ("$(DESTDIR)","") $(LDCONFIG) 2> /dev/null || true endif endif endif else $(INSTALL_DATA) $(DLLNAME) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION).$(REVISION)$(SHARED) $(LINK) -fs libsmooth-$(VERSION).$(REVISION)$(SHARED) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED) ifeq ($(BUILD_V8),True) $(INSTALL_DATA) $(LIBDIR)/libsmooth-js-$(VERSION)$(SHARED) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION).$(REVISION)$(SHARED) $(LINK) -fs libsmooth-js-$(VERSION).$(REVISION)$(SHARED) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED) endif endif $(INSTALL) -d "$(DESTDIR)"$(bindir) $(INSTALL_PROGRAM) $(BINDIR)/translator "$(DESTDIR)"$(bindir)/smooth-translator $(INSTALL) -d "$(DESTDIR)"$(includedir) $(COPY) -r "$(SRCDIR)"/include/smooth "$(DESTDIR)"$(includedir) $(CHMOD) -R a=rX,u=rwX "$(DESTDIR)"$(includedir)/smooth ifeq ($(BUILD_V8),True) $(COPY) -r "$(SRCDIR)"/include/smooth-js "$(DESTDIR)"$(includedir) $(CHMOD) -R a=rX,u=rwX "$(DESTDIR)"$(includedir)/smooth-js endif $(INSTALL_DATA) "$(SRCDIR)"/include/smooth.h "$(DESTDIR)"$(includedir) endif uninstall: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED) $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED).$(REVISION) ifeq ($(BUILD_V8),True) $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED) $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED).$(REVISION) endif ifneq ($(BUILD_SOLARIS),True) ifneq ($(BUILD_HAIKU),True) ifeq ("$(DESTDIR)","") $(LDCONFIG) 2> /dev/null || true endif endif endif else $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED) $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION).$(REVISION)$(SHARED) ifeq ($(BUILD_V8),True) $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED) $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION).$(REVISION)$(SHARED) endif endif $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(bindir)/smooth-translator $(REMOVE) $(REMOVE_OPTS) -r "$(DESTDIR)"$(includedir)/smooth ifeq ($(BUILD_V8),True) $(REMOVE) $(REMOVE_OPTS) -r "$(DESTDIR)"$(includedir)/smooth-js endif $(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(includedir)/smooth.h endif clean: $(call cleanin,classes) $(call cleanin,misc) $(call cleanin,resources) $(call cleanin,tools) $(call cleanin,samples) $(REMOVE) $(REMOVE_OPTS) $(DLLNAME) $(LIBNAME) distclean: clean $(call cleanin,libraries) ifneq ("$(SRCDIR)","$(CURDIR)") rmdir $(SMOOTH_PATH)/$(BINDIR) $(SMOOTH_PATH)/$(LIBDIR) || true endif doc: doc-clean doxys doc-clean: rm -r -f doc/reference $(OBJECTS): objects $(DLLNAME): $(OBJECTS) | libs $(LD) $(OBJECTS) $(LINKER_OPTS) $(LDFLAGS) $(LIBS) ifeq ($(findstring release,$(config)),release) -countbuild BuildNumber endif smooth-0.9.11~git20260403.0230c0da/Makefile-commands000066400000000000000000000075311516402577000212250ustar00rootroot00000000000000########## smooth commands makefile ########## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options CCOPTS = -I"$(SRCDIR)"/$(SMOOTH_PATH)/include $(MYCCOPTS) RC = windres RCOPTS = -DSMOOTH_DLL -O coff LDOPTS = -L"$(SRCDIR)"/$(SMOOTH_PATH)/$(LIBDIR) $(LIBS) ifndef GLOBALDLL CCOPTS += -fvisibility=hidden ifeq ($(BUILD_WIN32),True) LDOPTS += -lsmooth else LDOPTS += -lsmooth-$(VERSION) endif endif ifeq ($(BUILD_WIN32),True) CCOPTS += -DUNICODE -D_UNICODE LDOPTS += -mwindows -Wl,--dynamicbase,--nxcompat ifdef IMPORTLIB ifdef GLOBALDLL LDOPTS += -Wl,--out-implib,$(SMOOTH_PATH)/$(LIBDIR)/$(IMPORTLIB) else LDOPTS += -Wl,--out-implib,$(IMPORTLIB) endif endif ifeq ($(BUILD_X86),True) RCOPTS += --target=pe-i386 else ifeq ($(BUILD_X86_64),True) RCOPTS += --target=pe-x86-64 else ifeq ($(BUILD_ARM64),True) RC = aarch64-w64-mingw32-windres endif else CCOPTS += -fPIC ifneq ($(BUILD_SOLARIS),True) ifneq ($(BUILD_HAIKU),True) CCOPTS += -pthread endif endif ifdef GLOBALDLL ifeq ($(BUILD_OSX),True) LDOPTS += -Wl,-dylib_install_name,lib$(GLOBALDLL)-$(VERSION).$(REVISION)$(SHARED) else LDOPTS += -Wl,-soname,lib$(GLOBALDLL)-$(VERSION)$(SHARED).$(REVISION) endif endif ifeq ($(BUILD_OPENBSD),True) LDOPTS += -L/usr/X11R6/lib -L/usr/local/lib endif endif ifndef GLOBALLIB ifndef GLOBALEXE ifndef GLOBALDLL ifndef LOCALEXE ifndef LOCALDLL CCOPTS += -DSMOOTH_DLL endif endif endif endif endif .SUFFIXES: .mm .rc TARGETS = ifdef GLOBALLIB TARGETS += $(SMOOTH_PATH)/$(LIBDIR)/$(GLOBALLIB) endif ifdef GLOBALEXE TARGETS += $(SMOOTH_PATH)/$(BINDIR)/$(GLOBALEXE)$(EXECUTABLE) endif ifdef GLOBALDLL ifeq ($(BUILD_WIN32),True) TARGETS += $(SMOOTH_PATH)/$(BINDIR)/$(GLOBALDLL)$(SHARED) TARGETS += $(SMOOTH_PATH)/$(LIBDIR)/$(IMPORTLIB) else TARGETS += $(SMOOTH_PATH)/$(LIBDIR)/lib$(GLOBALDLL)-$(VERSION)$(SHARED) endif endif ifdef LOCALEXE TARGETS += $(LOCALEXE)$(EXECUTABLE) endif ifdef LOCALDLL TARGETS += $(LOCALDLL)$(SHARED) ifeq ($(BUILD_WIN32),True) TARGETS += $(IMPORTLIB) endif endif all: allcmds $(OBJECTS) $(TARGETS) allcmds: + $(ALLCMD1) + $(ALLCMD2) + $(ALLCMD3) + $(ALLCMD4) clean: ifdef OBJECTS rm -f $(OBJECTS) endif ifdef TARGETS rm -f $(TARGETS) endif $(CLEANCMD1) $(CLEANCMD2) $(CLEANCMD3) $(CLEANCMD4) .c.o: $(CC) $(CCOPTS) $(CFLAGS) -c $< -o $@ .cc.o: $(CXX) $(CCOPTS) $(CXXFLAGS) -c $< -o $@ .cpp.o: $(CXX) $(CCOPTS) $(CXXFLAGS) -c $< -o $@ .m.o: $(OBJC) $(CCOPTS) $(OBJCFLAGS) -c $< -o $@ .mm.o: $(OBJCXX) $(CCOPTS) $(OBJCXXFLAGS) -c $< -o $@ .rc.o: $(RC) $(RCOPTS) $< -o $@ ifdef GLOBALLIB $(SMOOTH_PATH)/$(LIBDIR)/$(GLOBALLIB): $(OBJECTS) mkdir -p $(SMOOTH_PATH)/$(LIBDIR) $(AR) rs $@ $(OBJECTS) endif ifdef GLOBALEXE $(SMOOTH_PATH)/$(BINDIR)/$(GLOBALEXE)$(EXECUTABLE): $(OBJECTS) mkdir -p $(SMOOTH_PATH)/$(BINDIR) $(LD) -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS) endif ifdef GLOBALDLL ifeq ($(BUILD_WIN32),True) $(SMOOTH_PATH)/$(BINDIR)/$(GLOBALDLL)$(SHARED): $(OBJECTS) mkdir -p $(SMOOTH_PATH)/$(BINDIR) else $(SMOOTH_PATH)/$(LIBDIR)/lib$(GLOBALDLL)-$(VERSION)$(SHARED): $(OBJECTS) endif mkdir -p $(SMOOTH_PATH)/$(LIBDIR) ifneq ($(BUILD_OSX),True) $(LD) --shared -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS) else $(LD) -dynamiclib -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS) endif ifeq ($(BUILD_WIN32),True) $(SMOOTH_PATH)/$(LIBDIR)/$(IMPORTLIB): $(SMOOTH_PATH)/$(BINDIR)/$(GLOBALDLL)$(SHARED) endif endif ifdef LOCALEXE $(LOCALEXE)$(EXECUTABLE): $(OBJECTS) $(LD) -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS) endif ifdef LOCALDLL $(LOCALDLL)$(SHARED): $(OBJECTS) ifneq ($(BUILD_OSX),True) $(LD) --shared -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS) else $(LD) -dynamiclib -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS) endif ifeq ($(BUILD_WIN32),True) $(IMPORTLIB): $(LOCALDLL)$(SHARED) endif endif smooth-0.9.11~git20260403.0230c0da/Makefile-options000066400000000000000000000272121516402577000211150ustar00rootroot00000000000000########## smooth options makefile ########## VERSION = 0.9 REVISION = 0 # Find source folder and set vpath SRCDIR = $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) vpath %.c "$(SRCDIR)" vpath %.cc "$(SRCDIR)" vpath %.cpp "$(SRCDIR)" vpath %.m "$(SRCDIR)" vpath %.mm "$(SRCDIR)" vpath %.js "$(SRCDIR)" vpath %.py "$(SRCDIR)" vpath %.rc "$(SRCDIR)" # Define makein and cleanin macros ifeq ("$(SRCDIR)","$(CURDIR)") makein = cd $(1) && $(MAKE) $(2) && cd .. cleanin = cd $(1) && $(MAKE) clean && cd .. else makein = mkdir -p $(1) && cd $(1) && $(MAKE) -f "$(SRCDIR)"/$(1)/Makefile $(2) && cd .. cleanin = mkdir -p $(1) && cd $(1) && $(MAKE) -f "$(SRCDIR)"/$(1)/Makefile clean && cd .. && (rmdir $(1) || true) endif # Find architecture and system UNAME = $(shell uname) MACHINE = $(shell $(CC) -dumpmachine) ifneq ($(findstring arm,$(MACHINE)),) ifneq ($(BUILD_ARM),False) BUILD_ARM = True endif else ifneq ($(findstring aarch64,$(MACHINE)),) ifneq ($(BUILD_ARM64),False) BUILD_ARM64 = True endif else ifneq ($(findstring mips,$(MACHINE)),) ifneq ($(BUILD_MIPS),False) BUILD_MIPS = True endif else ifneq ($(findstring powerpc64,$(MACHINE)),) ifneq ($(BUILD_PPC64),False) BUILD_PPC64 = True endif else ifneq ($(findstring powerpc,$(MACHINE)),) ifneq ($(BUILD_PPC),False) BUILD_PPC = True endif else ifneq ($(findstring riscv64,$(MACHINE)),) ifneq ($(BUILD_RISCV64),False) BUILD_RISCV64 = True endif else ifneq ($(findstring x86_64,$(MACHINE)),) ifneq ($(BUILD_ARM64),True) ifneq ($(BUILD_X86),True) ifneq ($(BUILD_X86_64),False) BUILD_X86_64 = True endif endif endif else ifneq ($(findstring amd64,$(MACHINE)),) ifneq ($(BUILD_ARM64),True) ifneq ($(BUILD_X86),True) ifneq ($(BUILD_X86_64),False) BUILD_X86_64 = True endif endif endif else ifneq ($(findstring i586,$(MACHINE))$(findstring i686,$(MACHINE)),) ifneq ($(BUILD_ARM64),True) ifneq ($(BUILD_X86),False) ifneq ($(BUILD_X86_64),True) BUILD_X86 = True endif endif endif endif # Disable threads based timers BUILD_THREADSTIMER = False # Do not build V8 JavaScript library by default BUILD_V8 = False # Treat MSYS and MinGW the same ifneq ($(findstring MSYS,$(UNAME)),) UNAME = MINGW endif ifneq ($(findstring MINGW,$(UNAME)),) # Set executable and shared object extensions EXECUTABLE = .exe SHARED = .dll # Build using Win32 backends BUILD_WIN32 = True # Disable GDI+ backend by default BUILD_GDIPLUS = False else # Set executable and shared object extensions EXECUTABLE = SHARED = .so BUILD_UNIX = True # Build using XLib backends BUILD_XLIB = True # Build using Cairo graphics backend BUILD_CAIRO = True # Build using POSIX threads BUILD_POSIXTHREADS = True # Build using POSIX timers BUILD_POSIXTIMER = True ifeq ($(UNAME),Linux) BUILD_LINUX = True else ifeq ($(UNAME),FreeBSD) BUILD_FREEBSD = True else ifeq ($(UNAME),OpenBSD) BUILD_OPENBSD = True # Enable threads based timers BUILD_POSIXTIMER = False BUILD_THREADSTIMER = True else ifeq ($(UNAME),NetBSD) BUILD_NETBSD = True else ifeq ($(UNAME),SunOS) BUILD_SOLARIS = True else ifeq ($(UNAME),Haiku) BUILD_HAIKU = True # Disable POSIX timer backend BUILD_POSIXTIMER = False # Disable XLib and Cairo backends BUILD_XLIB = False BUILD_CAIRO = False else ifeq ($(UNAME),GNU) BUILD_GNU = True # Enable threads based timers BUILD_POSIXTIMER = False BUILD_THREADSTIMER = True else ifeq ($(UNAME),Darwin) # Set shared object extension SHARED = .dylib BUILD_OSX = True # Disable XLib and Cairo backends BUILD_XLIB = False BUILD_CAIRO = False # Disable POSIX timers BUILD_POSIXTIMER = False endif endif # Set default commands ifndef OBJC OBJC = $(CC) endif ifndef OBJCXX OBJCXX = $(CXX) endif ifeq ($(LD),ld) LD = $(CXX) endif LDCONFIG = /sbin/ldconfig INSTALL = install ifeq ($(BUILD_SOLARIS),True) INSTALL = ginstall endif INSTALL_PROGRAM = $(INSTALL) INSTALL_DATA = $(INSTALL) -m 644 # Set output folders BINDIR = bin LIBDIR = lib ifeq ($(BUILD_WIN32),True) ifeq ($(BUILD_X86_64),True) BINDIR = bin64 LIBDIR = lib64 endif endif # Set install folders ifndef prefix prefix = /usr/local ifeq ($(BUILD_HAIKU),True) prefix = /system/non-packaged endif endif bindir = $(prefix)/bin libdir = $(prefix)/lib includedir = $(prefix)/include datadir = $(prefix)/share ifeq ($(BUILD_HAIKU),True) includedir = $(prefix)/develop/headers datadir = $(prefix)/data endif # Decide which libraries to use ifeq ($(findstring bundledlibbz2,$(config)),bundledlibbz2) USE_BUNDLED_LIBBZ2 = True else ifeq ($(findstring systemlibbz2,$(config)),systemlibbz2) USE_BUNDLED_LIBBZ2 = False else ifeq ($(BUILD_WIN32),True) USE_BUNDLED_LIBBZ2 = True endif endif ifeq ($(findstring bundledlibcpuid,$(config)),bundledlibcpuid) USE_BUNDLED_LIBCPUID = True else ifeq ($(findstring systemlibcpuid,$(config)),systemlibcpuid) USE_BUNDLED_LIBCPUID = False else USE_BUNDLED_LIBCPUID = True endif ifeq ($(findstring bundledlibcurl,$(config)),bundledlibcurl) USE_BUNDLED_LIBCURL = True else ifeq ($(findstring systemlibcurl,$(config)),systemlibcurl) USE_BUNDLED_LIBCURL = False else ifeq ($(BUILD_WIN32),True) USE_BUNDLED_LIBCURL = True endif endif ifeq ($(findstring bundledlibfribidi,$(config)),bundledlibfribidi) USE_BUNDLED_LIBFRIBIDI = True else ifeq ($(findstring systemlibfribidi,$(config)),systemlibfribidi) USE_BUNDLED_LIBFRIBIDI = False else ifeq ($(BUILD_OSX),True) USE_BUNDLED_LIBFRIBIDI = True else ifeq ($(BUILD_WIN32),True) USE_BUNDLED_LIBFRIBIDI = True endif endif ifeq ($(findstring bundledlibiconv,$(config)),bundledlibiconv) USE_BUNDLED_LIBICONV = True else ifeq ($(findstring systemlibiconv,$(config)),systemlibiconv) USE_BUNDLED_LIBICONV = False else ifeq ($(BUILD_WIN32),True) USE_BUNDLED_LIBICONV = True endif endif ifeq ($(findstring bundledlibjpeg,$(config)),bundledlibjpeg) USE_BUNDLED_LIBJPEG = True else ifeq ($(findstring systemlibjpeg,$(config)),systemlibjpeg) USE_BUNDLED_LIBJPEG = False else ifeq ($(BUILD_OSX),True) USE_BUNDLED_LIBJPEG = True else ifeq ($(BUILD_SOLARIS),True) USE_BUNDLED_LIBJPEG = True else ifeq ($(BUILD_WIN32),True) USE_BUNDLED_LIBJPEG = True endif endif ifeq ($(findstring bundledlibpng,$(config)),bundledlibpng) USE_BUNDLED_LIBPNG = True else ifeq ($(findstring systemlibpng,$(config)),systemlibpng) USE_BUNDLED_LIBPNG = False else ifeq ($(BUILD_OSX),True) USE_BUNDLED_LIBPNG = True else ifeq ($(BUILD_WIN32),True) USE_BUNDLED_LIBPNG = True endif endif ifeq ($(findstring bundledlibwebp,$(config)),bundledlibwebp) USE_BUNDLED_LIBWEBP = True else ifeq ($(findstring systemlibwebp,$(config)),systemlibwebp) USE_BUNDLED_LIBWEBP = False else USE_BUNDLED_LIBWEBP = True endif ifeq ($(findstring bundledlibxml2,$(config)),bundledlibxml2) USE_BUNDLED_LIBXML2 = True else ifeq ($(findstring systemlibxml2,$(config)),systemlibxml2) USE_BUNDLED_LIBXML2 = False else ifeq ($(BUILD_WIN32),True) USE_BUNDLED_LIBXML2 = True endif endif ifeq ($(findstring bundledzlib,$(config)),bundledzlib) USE_BUNDLED_ZLIB = True else ifeq ($(findstring systemzlib,$(config)),systemzlib) USE_BUNDLED_ZLIB = False else ifeq ($(BUILD_OSX),True) USE_BUNDLED_ZLIB = True else ifeq ($(BUILD_WIN32),True) USE_BUNDLED_ZLIB = True endif endif # Set release specific options ifeq ($(findstring release,$(config)),release) ifeq ($(BUILD_FREEBSD),True) override CC = clang override CXX = clang++ override OBJC = clang override OBJCXX = clang++ override LD = clang++ else ifeq ($(BUILD_OSX),True) override CC = gcc override CXX = g++ override OBJC = gcc override OBJCXX = g++ override LD = g++ endif override CFLAGS = -pipe -g0 -Wall override CXXFLAGS = override OBJCFLAGS = override OBJCXXFLAGS = override LDFLAGS = -pipe ifneq ($(BUILD_SOLARIS),True) override CFLAGS += -Os endif ifneq ($(RTTI),True) ifneq ($(BUILD_HAIKU),True) override CXXFLAGS += -fno-rtti override OBJCXXFLAGS += -fno-rtti endif endif ifneq ($(EXCEPTION),True) override CXXFLAGS += -fno-exceptions override OBJCXXFLAGS += -fno-exceptions endif ifeq ($(BUILD_OSX),True) # Find macOS and Xcode version XCODEVERSION = $(shell xcodebuild -version | head -n1) MACOSVERSION = $(MACOSX_DEPLOYMENT_TARGET) ifeq ($(MACOSVERSION),) MACOSVERSION = $(shell sw_vers | awk '$$1 == "ProductVersion:" { print $$2 }') endif XCODE_LE3 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#\#* }; if [ \$${v%%.*} -le 3 ]; then echo True; fi") XCODE_LE9 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#\#* }; if [ \$${v%%.*} -le 9 ]; then echo True; fi") XCODE_EQ12 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#\#* }; if [ \$${v%%.*} -eq 12 ]; then echo True; fi") XCODE_GE13 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#\#* }; if [ \$${v%%.*} -ge 13 ]; then echo True; fi") XCODE_N_GE2 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#*.}; if [ \$${v%%.*} -ge 2 ]; then echo True; fi") MACOS_GE11 = $(shell bash -c "v='$(MACOSVERSION)'; if [ \$${v%%.*} -ge 11 ]; then echo True; fi") # Build universal binaries ifneq ($(BUILD_X86_64),False) BUILD_X86_64 = True endif ifeq ($(XCODE_LE9),True) ifneq ($(BUILD_X86),False) BUILD_X86 = True endif ifeq ($(XCODE_LE3),True) ifneq ($(BUILD_PPC),False) BUILD_PPC = True endif endif else ifeq ($(XCODE_EQ12),True) ifeq ($(XCODE_N_GE2),True) ifeq ($(MACOS_GE11),True) ifneq ($(BUILD_ARM64),False) BUILD_ARM64 = True endif endif endif else ifeq ($(XCODE_GE13),True) ifeq ($(MACOS_GE11),True) ifneq ($(BUILD_ARM64),False) BUILD_ARM64 = True endif endif endif # Set build flags override LDFLAGS += -Wl,-x ifeq ($(BUILD_X86),True) override CFLAGS += -arch i386 -Xarch_i386 -march=prescott override LDFLAGS += -arch i386 endif ifeq ($(BUILD_X86_64),True) ifeq ($(MACOS_GE11),True) override CFLAGS += -arch x86_64 -Xarch_x86_64 -march=haswell else override CFLAGS += -arch x86_64 -Xarch_x86_64 -march=core2 endif override LDFLAGS += -arch x86_64 endif ifeq ($(BUILD_PPC),True) override CFLAGS += -arch ppc -Xarch_ppc -mcpu=G4 override LDFLAGS += -arch ppc endif ifeq ($(BUILD_PPC64),True) override CFLAGS += -arch ppc64 -Xarch_ppc64 -mcpu=G5 override LDFLAGS += -arch ppc64 endif ifeq ($(BUILD_ARM64),True) override CFLAGS += -arch arm64 override LDFLAGS += -arch arm64 endif else override LDFLAGS += -s ifeq ($(BUILD_X86),True) override CFLAGS += -m32 override LDFLAGS += -m32 else ifeq ($(BUILD_X86_64),True) override CFLAGS += -m64 override LDFLAGS += -m64 endif endif override CXXFLAGS += $(CFLAGS) override OBJCFLAGS += $(CFLAGS) override OBJCXXFLAGS += $(CFLAGS) ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) LDFLAGS_TOOLS += -Wl,-rpath,. endif endif endif # Set debug specific options ifeq ($(findstring debug,$(config)),debug) override CFLAGS = -pipe -g -Wall -DDEBUG override CXXFLAGS = override OBJCFLAGS = override OBJCXXFLAGS = override LDFLAGS = -pipe ifneq ($(RTTI),True) ifneq ($(BUILD_HAIKU),True) override CXXFLAGS += -fno-rtti override OBJCXXFLAGS += -fno-rtti endif endif ifneq ($(EXCEPTION),True) override CXXFLAGS += -fno-exceptions override OBJCXXFLAGS += -fno-exceptions endif override CXXFLAGS += $(CFLAGS) override OBJCFLAGS += $(CFLAGS) override OBJCXXFLAGS += $(CFLAGS) ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) override LDFLAGS_TOOLS += -Wl,-rpath,. endif endif endif # Flags needed for Windows ARM64 toolchain ifeq ($(BUILD_WIN32),True) ifeq ($(BUILD_ARM64),True) override CFLAGS += -target aarch64-w64-mingw32 override LDFLAGS += -target aarch64-w64-mingw32 endif endif # Clear config variable config = smooth-0.9.11~git20260403.0230c0da/Readme.md000066400000000000000000000034611516402577000175030ustar00rootroot00000000000000The smooth Class Library ==================================================================================================== [![Build Status](https://img.shields.io/github/actions/workflow/status/enzo1982/smooth/verify-build.yml?branch=master)](https://github.com/enzo1982/smooth/actions?query=workflow%3A%22Verify+build%22+branch%3Amaster) [![Last commit](https://img.shields.io/github/last-commit/enzo1982/smooth.svg)](https://github.com/enzo1982/smooth/commits/master) [![License](https://img.shields.io/github/license/enzo1982/smooth.svg)](https://github.com/enzo1982/smooth/blob/master/Copying) _smooth_ is an object oriented C++ class library for Windows, macOS, Linux and most Unix-like operating systems. It provides basic functionality and platform support for applications and libraries. Features provided by _smooth_ include: - user interface API with various widgets - simple to use multithreading API - file and network IO interface - completely transparent Unicode and software internationalization support - a libxml2 based XML parser Installation ------------ The following packages must be installed in order to compile _smooth_: - libbz2 / libbzip2 development package - libcurl development package - libfribidi development package - libgtk+3.0 development package - libjpeg development package - libxml2 development package After installing these prerequisites, run `make` followed by `sudo make install` to compile and install _smooth_. License ------- _smooth_ is Free Software and is made available under the terms of "The Artistic License, Version 2.0". ---------------------------------------------------------------------------------------------------- The official _smooth_ homepage: http://www.smooth-project.org/ robert.kausch@freac.org,
Robert Kausch smooth-0.9.11~git20260403.0230c0da/ToDo.xml000066400000000000000000002026171516402577000173570ustar00rootroot00000000000000 ToDo --------- - save the last ~100 conversion results - avoid calls to MultiByteToWideChar and WideCharToMultiByte ToDo --------- - replace smooth::Client with smooth::Canvas and allow direct drawing operations ToDo --------- - protected inheritance from Array<> - pseudo signal (is a function returning a signal) - real signals stored in the Array - Int Add(Int id) { return Array::Add(signalTYPE(), id); } - Int Remove(Int id) { return Array::Remove(id); } - Signal0<Void> &operator ()(Int id) { return Array::GetReference(id); } - can be filled like this MultiSignal<Signal0<Void>> onSignal; onSignal.Add(argument); onSignal.Remove(argument); - can be called like this object->onSignal(argument).Connect(...); object->onSignal(argument).Emit(); - argument is an integer ToDo --------- - implement a keyboard interface (i.e. a method for Widgets to handle keyboard input) Singleton - key constants like Keyboard::RETURN replace Windows VK_* constants - use multisignals to get key events - multisignal index is value of key constant - onKeyDown, onKeyUp - replaces WM_KEY* messages - alternatively use single signal with key code as argument - function IsKeyDown Singleton - use a signal for character input - replaces WM_CHAR messages ToDo --------- - implement a mouse interface (although probably used more seldom) Singleton - multisignals onButtonDown, onButtonUp - replaces WM_*BUTTON* messages - signal onMouseMove - replaces WM_MOUSEMOVE message ToDo ---------- Skizze für eine Layout-Engine für smooth: Container erhalten einen Layout-Manager-Decorator, der sich um die Anordnung der Elemente kümmert. Es gibt verschiedene, auswechselbare Layout-Manager mit unterschiedlichen Grundlayouts. Für Container kann die X- und Y-Ausrichtung der Elemente angegeben werden (topleft, topmiddle, topright, middleleft, middle, middleright, bottomleft, bottommiddle, bottomright). Elemente brauchen eine Y-Offset-Position, damit der Layout-Manager weiß, auf welcher Höhe sie ausgerichtet werden müssen, um Text auf der gleichen Ebene zu erhalten. Beispiel: Die meisten Elemente haben Y-Offset 0, Text-Elemente haben Offset 3 und Button Elemente Offset -1. Elemente können unabhängig vom Layout-Manager auch absolut positioniert werden. Elemente können mehrere Felder eines Grid-Layouts einnehmen (rowspan, colspan). Elemente können Breitenanpassung zulassen oder feste Breite definieren. ExcAAHic7VfJbtswEO3ZQP6BN7eFVUjymuQUN057aNACzqEBdKGskUSYIgWSshMH/vcOSTmLe3N7iwKDw+WRYmYeH4dPiTJ5lFChmStWdRHF4zjJIM9DW3IqiigcRk9JLoUxKcdKmOSC8SRflVRpMCG5XZIlziZLUCy/3CMkeguJyfKxSiW/3O/PesmGwXbNRDZKmlWU1FRliXmYjEIso3jmzHlsTTyeWDOMQ2dmDjIaOcg4cpDx1EFwtjXT0EGmEweZDR1kdu4gWLqlw9h/KZz5T0Xj2H85mhx24Oxw5HGj0ONGU48bDz0Ol/O23fm03frU7z2a+c3bf8Vbv/04tPu3PtTRjNzJa2k9cNYLnv9825fLNdvtgORJP18pAkwA+UEfZWOChShsqx3RlZSmvHg91Tn2KamFgQdjI9KfTxNDUwzPZ+zFH9/wlBus4GAtMCAgTOhmPJjUwvf79xYY8hVZTtGx6GxVUm5AOK+Lg9tvqaAFqOAaVlJRI9WAZAjGk1OSpiIZA3IlpMpEIwo3suBQoV+BrG2kqgqU+fIqQO/NwR03T+fmQpOCpYZsQOlVyQB9AgNCG72FVamBp1TBEU9JxQxp0M3tDI48RTJ/U43IuEPqjo0dG09h442/eV4Ec02FcAL4O0DKZeQ+uGq0QsKZv7QQkwooIEUmbkGhM8lHI2sOuRkQrFQsyzi4qmJFiZ2+xwMOo962gFQaIysP8PUDzLcc7FNH9Y7qJwnvgbepoo0TUJeJ3Qc/8xyz2+CX1MwwKTAXoFZwLdePdHgLLOlnuZXrHBscV1HkOx6hSQmYPYCVccTZ0wLmcCoqe8S0BlwYc4s7DJmbbpcvOHgpX+ApArJrnvOVjuQdyU8h+RyYrhnwC3KNdKywZZPfZ+qX1Mr1gfIkHDg+Bkfj7ejQXQDzBqX31RLtYBB1FO0oegpF3z6mJsK+yxpB0zLpwwjfwwXZyOpYea1iE5pqyRtD6lapGT7DWpXtyNiR8Z+SghcuVlAqwDfYDXB7R9skQeNbi2WB56S2XQLKyma8Sm51TfFqX0luK1122hHxfxFxroDh7U1FTbW2r69dw6lNJIm0xMwB7/YWhNlkzqwedkp41tuf9T78AWMGOH0AAA== Themes in smooth ----------------------------- Der Theme-Programmierer schreibt Klassen, welche die Originalklassen ersetzen z.B.: class ColorfulButton : public Button { public: ColorfulButton(const Button &); virtual Int Paint(Int); }; Dabei können (sollten) die Paint- und Process-Funktionen überschrieben werden. Außerdem muss ein Kopierkonstruktor für die Basisklasse vorhanden sein. Dann wird in einer Initialisierungsfunktion deklariert, wie die Klasse eingesetzt werden soll: Object::DeclareReplacement(Button::classID, ColorfulButton::classID); Die smooth-Klassenbibliothek ersetzt dann automatisch alle Buttons durch ColorfulButtons. Diese Ersetzung geschiet bei der Registrierung eines Buttons bei einem Container. Object::GetReplacementFor(object); --> Object *GetReplacementFor(Object *object) { if (replacementClassIDs.GetEntry(object->classID) != 0) { return CreateObjectByClassIDFrom(replacementClassIDs.GetEntry(object->classID), object); } return object; } Die Theme-Klassen werden in einer DLL-Datei zusammengefasst (oder direkt in eine EXE-Datei eingebunden), welche dann über eine spezielle Funktion aktiviert wird. Easily Customizable Menus ------------------------------------------- Rechtsklick auf einen Menüeintrag öffnet ein Kontextmenü. Funktionen: Umbenennen, Entfernen, Neuer Eintrag, Eigenschaften, Shortcut ändern Im Eigenschaften Dialog kann unter anderem die Aktion definiert werden, die ausgeführt werden soll. Dazu werden im Programmcode Aktionen registriert (mit Application als Container). Möglicherweise sollte es vordefinierte Aktionen geben (z.B. ExitProgram). Außerdem: Bild und Text eines Eintrags können verändert werden Font("Times", 18, Font::Bold) e.g. Font::Bold, Font::Italic Note -------- Implemented as an additional array specifying the order of elements in a list. ToDo --------- - part of class Widget - set context menu using getContextMenu callback - send a signal before opening menu - open menu upon SM_RBUTTONDOWN ToDo --------- An idea: #define foreach(type,var,array) array.InitializeIndex(#var#); for (type var;var=array.GetNth(array.GetIndexValue(#var#)),count<array.Length();array.IncrementIndex(#var#)) Array<String> strings; foreach (String, s, strings) { } ToDo --------- - Template-Datei wird in Übersetzungsdatei angegeben - Translator zeigt fehlende (rot), geänderte (orange) und übersetzte Einträge (schwarz) TreeWidget ------------------- Trees werden als spezielle ListEntries implementiert. Mit einem Button zum öffnen des Subtrees. Dabei ist der Tree für die ListBox nur ein einziger Eintrag. Der Subtree wird ebenfalls wieder als ListBox implementiert (Child des TreeListEntries). Die alte Tree-Implementierung wird damit überflüssig. smooth-0.9.11~git20260403.0230c0da/classes/000077500000000000000000000000001516402577000174155ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/Makefile000066400000000000000000000007631516402577000210630ustar00rootroot00000000000000########## smooth directory $(MAKE)file ########## # Change these variables to fit this location: SMOOTH_PATH = .. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options FOLDERS = backends basic errors files graphics gui i18n input io misc net system threads xml .PHONY: $(FOLDERS) all: $(FOLDERS) $(FOLDERS): + $(call makein,$@) clean: $(foreach FOLDER,$(FOLDERS),$(FOLDER)##clean) $(foreach FOLDER,$(FOLDERS),$(FOLDER)##clean): $(call cleanin,$(subst ##clean,,$@)) smooth-0.9.11~git20260403.0230c0da/classes/backends/000077500000000000000000000000001516402577000211675ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/backends/Makefile000066400000000000000000000012141516402577000226250ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. # Enter object files here: OBJECTS = backend.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,cocoa) && $(call makein,gdiplus) ALLCMD2 = $(call makein,haiku) && $(call makein,win32) ALLCMD3 = $(call makein,xlib) CLEANCMD1 = $(call cleanin,cocoa) && $(call cleanin,gdiplus) CLEANCMD2 = $(call cleanin,haiku) && $(call cleanin,win32) CLEANCMD3 = $(call cleanin,xlib) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/backends/backend.cpp000066400000000000000000000045751516402577000232750ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2011 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::Array *S::Backends::Backend::backends = NIL; S::Array *S::Backends::Backend::backend_creators = NIL; S::Int S::Backends::Backend::AddBackend(Backend *(*backend)()) { if (backend == NIL) return Error(); if (backend_creators == NIL) backend_creators = new Array; backend_creators->Add(backend); return Success(); } S::Int S::Backends::Backend::GetNOfBackends() { return backends->Length(); } S::Backends::Backend *S::Backends::Backend::GetNthBackend(Int n) { return backends->GetNth(n); } S::Int S::Backends::Backend::InitBackends() { if (backends == NIL) backends = new Array; if (backend_creators == NIL) backend_creators = new Array; for (Int i = 0; i < backend_creators->Length(); i++) { backends->Add(backend_creators->GetNth(i)()); } for (Int i = 0; i < backends->Length(); i++) { if (backends->GetNth(i)->Init() == Error()) { /* Deinit already initialized backends and return. */ for (Int j = i - 1; j >= 0; j--) backends->GetNth(j)->Deinit(); return Error(); } } return Success(); } S::Int S::Backends::Backend::DeinitBackends() { for (Int i = 0; i < backends->Length(); i++) { backends->GetNth(i)->Deinit(); delete backends->GetNth(i); } backends->RemoveAll(); delete backends; delete backend_creators; return Success(); } S::Backends::Backend::Backend() { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) BackendWin32(); #endif type = BACKEND_NONE; } S::Backends::Backend::~Backend() { } S::Int S::Backends::Backend::Init() { return Success(); } S::Int S::Backends::Backend::Deinit() { return Success(); } S::Short S::Backends::Backend::GetBackendType() const { return type; } smooth-0.9.11~git20260403.0230c0da/classes/backends/cocoa/000077500000000000000000000000001516402577000222535ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/backends/cocoa/Makefile000066400000000000000000000006471516402577000237220ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_OSX),True) OBJECTS += backendcocoa.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/backends/cocoa/backendcocoa.mm000066400000000000000000000247131516402577000252110ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2025 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include using namespace smooth; using namespace smooth::GUI; S::Backends::Backend *CreateBackendCocoa() { return new S::Backends::BackendCocoa(); } S::Int backendCocoaTmp = S::Backends::Backend::AddBackend(&CreateBackendCocoa); #if defined MAC_OS_X_VERSION_10_6 && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 @interface CocoaApplicationDelegate : NSObject { } #else @interface CocoaApplicationDelegate : NSObject { } #endif - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) sender; - (void) application: (NSApplication *) sender openFiles: (NSArray *) fileNames; - (DropArea *) findDropArea: (Widget *) container; @end @implementation CocoaApplicationDelegate - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) sender { /* Send a dummy event to allow NSApp::run to exit. */ NSEvent *event = [NSEvent otherEventWithType: NSApplicationDefined location: NSMakePoint(0, 0) modifierFlags: 0 timestamp: 0 windowNumber: 0 context: nil subtype: 0 data1: 0 data2: 0]; [NSApp postEvent: event atStart: YES]; [NSApp stop: self]; /* Request application to quit. */ System::EventCocoa::RequestApplicationQuit(); /* Application will terminate after all windows are closed. */ return NSTerminateCancel; } - (void) application: (NSApplication *) sender openFiles: (NSArray *) fileNames { /* Look for a window with a drop area. */ DropArea *dropArea = NIL; for (Int n = 0; n < Window::GetNOfWindows(); n++) { Window *window = Window::GetNthWindow(n); if (!window->IsVisible()) continue; if ((dropArea = [self findDropArea: window]) != NIL) break; } /* Check whether a drop area has been found. */ if (dropArea == NIL) { [sender replyToOpenOrPrint: NSApplicationDelegateReplyFailure]; return; } /* Simulate arrival of the files via drag & drop. */ Array files; for (UnsignedInt i = 0; i < [fileNames count]; i++) { String file; file.ImportFrom("UTF-8", [[fileNames objectAtIndex: i] UTF8String]); files.Add(file); dropArea->onDropFile.Emit(file); } dropArea->onDropFiles.Emit(files); [sender replyToOpenOrPrint: NSApplicationDelegateReplySuccess]; } - (DropArea *) findDropArea: (Widget *) container { for (Int n = 0; n < container->GetNOfObjects(); n++) { Widget *widget = container->GetNthObject(n); if (widget->GetObjectType() == DropArea::classID && widget->IsActive()) return (DropArea *) widget; DropArea *dropArea = [self findDropArea: widget]; if (dropArea != NIL) return dropArea; } return NIL; } @end S::Backends::BackendCocoa::BackendCocoa() { type = BACKEND_COCOA; pool = nil; } S::Backends::BackendCocoa::~BackendCocoa() { } S::Int S::Backends::BackendCocoa::Init() { /* Init the Cocoa app. */ [NSApplication sharedApplication]; /* Create a garbage collection pool. */ pool = [[NSAutoreleasePool alloc] init]; /* Set application delegate. */ [NSApp setDelegate: [[[CocoaApplicationDelegate alloc] init] autorelease]]; /* Get default colors. */ UpdateColors(); /* Set default language if not set. */ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSArray *languages = [defaults objectForKey: @"AppleLanguages"]; NSString *language = [languages objectAtIndex: 0]; setenv("LANG", [language UTF8String], False); return Success(); } S::Int S::Backends::BackendCocoa::Deinit() { /* Release our garbage collection pool. */ [pool release]; return Success(); } S::Void S::Backends::BackendCocoa::UpdateColors() { /* Create a dummy window to retrieve its background color. * * This does not work in macOS 10.10 to 10.13, so we check if it returned * a meaningful color and assign a light gray default value otherwise. */ NSWindow *window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 0, 0) styleMask: NSTitledWindowMask backing: NSBackingStoreBuffered defer: YES]; NSColor *windowBackground = [[window backgroundColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace]; if ([windowBackground redComponent] == 0 && [windowBackground greenComponent] == 0 && [windowBackground blueComponent] == 0) windowBackground = [NSColor colorWithDeviceRed: 0.9 green: 0.9 blue: 0.9 alpha: 1.0]; [window release]; /* Query the other UI colors. */ NSColor *text = [[NSColor textColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace]; NSColor *textBackground = [[NSColor textBackgroundColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace]; NSColor *controlText = [[NSColor controlTextColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace]; NSColor *disabledControlText = [[NSColor disabledControlTextColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace]; NSColor *selectedText = [[NSColor selectedTextColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace]; NSColor *selectedTextBackground = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace]; NSColor *alternateSelectedControl = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace]; NSColor *alternateSelectedControlText = [[NSColor alternateSelectedControlTextColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace]; if ([disabledControlText redComponent] == 0 && [disabledControlText greenComponent] == 0 && [disabledControlText blueComponent] == 0) disabledControlText = [NSColor colorWithDeviceRed: 0.5 green: 0.5 blue: 0.5 alpha: 1.0]; /* Query link color if selector exists. */ static SEL linkColorSelector = @selector(linkColor); static Bool canQueryLinkColor = [[NSColor class] respondsToSelector: linkColorSelector]; NSColor *linkColor = nil; if (canQueryLinkColor) linkColor = [((NSColor *(*)(id, SEL)) [[NSColor class] methodForSelector: linkColorSelector])([NSColor class], linkColorSelector) colorUsingColorSpaceName: NSDeviceRGBColorSpace]; /* Convert to smooth colors. */ Setup::BackgroundColor = GUI::Color([windowBackground redComponent] * 255, [windowBackground greenComponent] * 255, [windowBackground blueComponent] * 255); Setup::LightGrayColor = GUI::Color(([windowBackground redComponent] + (1.0 - [windowBackground redComponent]) * 0.6) * 255, ([windowBackground greenComponent] + (1.0 - [windowBackground greenComponent]) * 0.6) * 255, ([windowBackground blueComponent] + (1.0 - [windowBackground blueComponent]) * 0.6) * 255); Setup::ClientColor = GUI::Color([textBackground redComponent] * 255, [textBackground greenComponent] * 255, [textBackground blueComponent] * 255); Setup::ClientTextColor = GUI::Color([text redComponent] * 255, [text greenComponent] * 255, [text blueComponent] * 255); Setup::DividerLightColor = GUI::Color(([windowBackground redComponent] + (1.0 - [windowBackground redComponent]) * 0.6) * 255, ([windowBackground greenComponent] + (1.0 - [windowBackground greenComponent]) * 0.6) * 255, ([windowBackground blueComponent] + (1.0 - [windowBackground blueComponent]) * 0.6) * 255); Setup::DividerDarkColor = GUI::Color([windowBackground redComponent] * 0.7 * 255, [windowBackground greenComponent] * 0.7 * 255, [windowBackground blueComponent] * 0.7 * 255); Setup::TextColor = GUI::Color([controlText redComponent] * 255, [controlText greenComponent] * 255, [controlText blueComponent] * 255); Setup::InactiveTextColor = GUI::Color([disabledControlText redComponent] * 255, [disabledControlText greenComponent] * 255, [disabledControlText blueComponent] * 255); Setup::HighlightColor = GUI::Color([selectedTextBackground redComponent] * 255, [selectedTextBackground greenComponent] * 255, [selectedTextBackground blueComponent] * 255); Setup::HighlightTextColor = GUI::Color([selectedText redComponent] * 255, [selectedText greenComponent] * 255, [selectedText blueComponent] * 255); Setup::GradientStartColor = GUI::Color(([alternateSelectedControl redComponent] - [alternateSelectedControl redComponent] * 0.25) * 255, ([alternateSelectedControl greenComponent] - [alternateSelectedControl greenComponent] * 0.25) * 255, ([alternateSelectedControl blueComponent] - [alternateSelectedControl blueComponent] * 0.25) * 255); Setup::GradientEndColor = GUI::Color(([alternateSelectedControl redComponent] + (1.0 - [alternateSelectedControl redComponent]) * 0.25) * 255, ([alternateSelectedControl greenComponent] + (1.0 - [alternateSelectedControl greenComponent]) * 0.25) * 255, ([alternateSelectedControl blueComponent] + (1.0 - [alternateSelectedControl blueComponent]) * 0.25) * 255); Setup::GradientTextColor = GUI::Color([alternateSelectedControlText redComponent] * 255, [alternateSelectedControlText greenComponent] * 255, [alternateSelectedControlText blueComponent] * 255); if (linkColor != nil) { Setup::LinkColor = GUI::Color([linkColor redComponent] * 255, [linkColor greenComponent] * 255, [linkColor blueComponent] * 255); Setup::LinkHighlightColor = GUI::Color([linkColor redComponent] * 255, [linkColor greenComponent] * 255, [linkColor blueComponent] * 255); } if (Setup::InactiveTextColor == Setup::TextColor) { Setup::InactiveTextColor = Setup::InactiveTextColor.Average(Setup::BackgroundColor); } } S::Bool S::Backends::BackendCocoa::IsOSXVersionAtLeast(Int majorVersion, Int minorVersion, Int microVersion) { static SInt32 osMajorVersion = 0; static SInt32 osMinorVersion = 0; static SInt32 osMicroVersion = 0; if (osMajorVersion == 0) { Gestalt(gestaltSystemVersionMajor, &osMajorVersion); Gestalt(gestaltSystemVersionMinor, &osMinorVersion); Gestalt(gestaltSystemVersionBugFix, &osMicroVersion); } if ( osMajorVersion > majorVersion || (osMajorVersion == majorVersion && ( osMinorVersion > minorVersion || (osMinorVersion == minorVersion && osMicroVersion >= microVersion)))) return True; return False; } smooth-0.9.11~git20260403.0230c0da/classes/backends/gdiplus/000077500000000000000000000000001516402577000226365ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/backends/gdiplus/Makefile000066400000000000000000000006551516402577000243040ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_GDIPLUS),True) OBJECTS += backendgdiplus.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/backends/gdiplus/backendgdiplus.cpp000077500000000000000000000021541516402577000263260ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2011 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Backends::Backend *CreateBackendGDIPlus() { return new S::Backends::BackendGDIPlus(); } S::Int backendGDIPlusTmp = S::Backends::Backend::AddBackend(&CreateBackendGDIPlus); S::Backends::BackendGDIPlus::BackendGDIPlus() { type = BACKEND_GDIPLUS; } S::Backends::BackendGDIPlus::~BackendGDIPlus() { } S::Int S::Backends::BackendGDIPlus::Init() { Gdiplus::GdiplusStartupInput gdiplusStartupInput; /* Initialize GDI+. */ Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); return Success(); } S::Int S::Backends::BackendGDIPlus::Deinit() { Gdiplus::GdiplusShutdown(gdiplusToken); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/backends/haiku/000077500000000000000000000000001516402577000222705ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/backends/haiku/Makefile000066400000000000000000000006511516402577000237320ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_HAIKU),True) OBJECTS += backendhaiku.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/backends/haiku/backendhaiku.cpp000066400000000000000000000111171516402577000254060ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include namespace smooth { class HaikuApplication : public BApplication { private: static String GetAppSignature() { BResources resources(GUI::Application::GetCommand()); size_t size = 0; const char *signature = (const char *) resources.LoadResource('MIMS', "BEOS:APP_SIG", &size); if (signature) return signature; return String("application/x-vnd.").Append(File(GUI::Application::GetCommand()).GetFileName()); } public: HaikuApplication() : BApplication(GetAppSignature()) { } }; }; S::Backends::Backend *CreateBackendHaiku() { return new S::Backends::BackendHaiku(); } S::Int backenHaikuTmp = S::Backends::Backend::AddBackend(&CreateBackendHaiku); S::Backends::BackendHaiku::BackendHaiku() { type = BACKEND_HAIKU; } S::Backends::BackendHaiku::~BackendHaiku() { } S::Int S::Backends::BackendHaiku::Init() { /* Set locale to user default. */ setlocale(LC_ALL, ""); /* Get default colors. */ UpdateColors(); return Success(); } S::Int S::Backends::BackendHaiku::Deinit() { return Success(); } S::Void S::Backends::BackendHaiku::UpdateColors() { rgb_color panelBackground = ui_color(B_PANEL_BACKGROUND_COLOR); rgb_color panelText = ui_color(B_PANEL_TEXT_COLOR); rgb_color documentBackground = ui_color(B_DOCUMENT_BACKGROUND_COLOR); rgb_color documentText = ui_color(B_DOCUMENT_TEXT_COLOR); rgb_color windowTab = ui_color(B_WINDOW_TAB_COLOR); rgb_color windowText = ui_color(B_WINDOW_TEXT_COLOR); rgb_color tooltipBackground = ui_color(B_TOOL_TIP_BACKGROUND_COLOR); rgb_color tooltipText = ui_color(B_TOOL_TIP_TEXT_COLOR); rgb_color link = ui_color(B_LINK_TEXT_COLOR); rgb_color linkHover = ui_color(B_LINK_HOVER_COLOR); Setup::BackgroundColor = GUI::Color(panelBackground.red, panelBackground.green, panelBackground.blue); Setup::LightGrayColor = GUI::Color(panelBackground.red + (255 - panelBackground.red) * 0.6, panelBackground.green + (255 - panelBackground.green) * 0.6, panelBackground.blue + (255 - panelBackground.blue) * 0.6); Setup::ClientColor = GUI::Color(documentBackground.red, documentBackground.green, documentBackground.blue); Setup::ClientTextColor = GUI::Color(documentText.red, documentText.green, documentText.blue); Setup::DividerLightColor = GUI::Color(panelBackground.red + (255 - panelBackground.red) * 0.6, panelBackground.green + (255 - panelBackground.green) * 0.6, panelBackground.blue + (255 - panelBackground.blue) * 0.6); Setup::DividerDarkColor = GUI::Color(panelBackground.red * 0.7, panelBackground.green * 0.7, panelBackground.blue * 0.7); Setup::TextColor = GUI::Color(panelText.red, panelText.green, panelText.blue); Setup::InactiveTextColor = GUI::Color(panelText.red + (255 - panelText.red) * 0.5, panelText.green + (255 - panelText.green) * 0.5, panelText.blue + (255 - panelText.blue) * 0.5); Setup::HighlightColor = GUI::Color(windowTab.red + (255 - windowTab.red) * 0.5, windowTab.green + (255 - windowTab.green) * 0.5, windowTab.blue + (255 - windowTab.blue) * 0.5); Setup::HighlightTextColor = GUI::Color(documentText.red, documentText.green, documentText.blue); Setup::GradientStartColor = GUI::Color(windowTab.red, windowTab.green, windowTab.blue); Setup::GradientEndColor = GUI::Color(windowTab.red + (255 - windowTab.red) * 0.6, windowTab.green + (255 - windowTab.green) * 0.6, windowTab.blue + (255 - windowTab.blue) * 0.6); Setup::GradientTextColor = GUI::Color(windowText.red, windowText.green, windowText.blue); Setup::TooltipColor = GUI::Color(tooltipBackground.red, tooltipBackground.green, tooltipBackground.blue); Setup::TooltipTextColor = GUI::Color(tooltipText.red, tooltipText.green, tooltipText.blue); Setup::LinkColor = GUI::Color(link.red, link.green, link.blue); Setup::LinkHighlightColor = GUI::Color(linkHover.red, linkHover.green, linkHover.blue); } BApplication *S::Backends::BackendHaiku::GetApplication() { static HaikuApplication app; return be_app; } smooth-0.9.11~git20260403.0230c0da/classes/backends/win32/000077500000000000000000000000001516402577000221315ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/backends/win32/Makefile000066400000000000000000000011051516402577000235660ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifeq ($(USE_BUNDLED_LIBICONV),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support/libiconv endif # Enter object files here: OBJECTS = ifeq ($(BUILD_WIN32),True) OBJECTS += backendwin32.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/backends/win32/backendwin32.cpp000066400000000000000000000322321516402577000251110ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2023 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #define MAX_EXT_PATH 32768 size_t (*iconv)(iconv_t, char **, size_t *, char **, size_t *) = NIL; iconv_t (*iconv_open)(const char *, const char *) = NIL; int (*iconv_close)(iconv_t) = NIL; int (*iconvctl)(iconv_t, int, void *) = NIL; HINSTANCE iconvDLL = NIL; HINSTANCE hDllInstance = NIL; S::Bool S::LoadIconvDLL() { iconvDLL = LoadLibrary(GUI::Application::GetApplicationDirectory().Append("iconv")); iconv = (size_t (*)(iconv_t, char **, size_t *, char **, size_t *)) GetProcAddress(iconvDLL, "libiconv"); iconv_open = (iconv_t (*)(const char *, const char *)) GetProcAddress(iconvDLL, "libiconv_open"); iconv_close = (int (*)(iconv_t)) GetProcAddress(iconvDLL, "libiconv_close"); iconvctl = (int (*)(iconv_t, int, void *)) GetProcAddress(iconvDLL, "libiconvctl"); if (iconv == NIL || iconv_open == NIL || iconv_close == NIL || iconvctl == NIL) { FreeIconvDLL(); return False; } return True; } S::Void S::FreeIconvDLL() { FreeLibrary(iconvDLL); iconv = NIL; iconv_open = NIL; iconv_close = NIL; iconvctl = NIL; } #ifndef SMOOTH_STATIC extern "C" { BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved) { switch (reason) { case DLL_PROCESS_ATTACH: hDllInstance = hInst; break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return true; } } #endif static HMODULE user32dll = NIL; typedef BOOL (WINAPI* SETPROCESSDPIAWARE)(); static SETPROCESSDPIAWARE ex_SetProcessDPIAware = NIL; S::Backends::Backend *CreateBackendWin32() { return new S::Backends::BackendWin32(); } S::Int backendWin32Tmp = S::Backends::Backend::AddBackend(&CreateBackendWin32); S::Backends::BackendWin32::BackendWin32() { type = BACKEND_WIN32; } S::Backends::BackendWin32::~BackendWin32() { } S::Int S::Backends::BackendWin32::Init() { /* Init COM library. */ OleInitialize(NIL); /* Init Windows sockets. */ WORD wVersionRequested = MAKEWORD(2,2); WSADATA wsaData; WSAStartup(wVersionRequested, &wsaData); /* Declare the process DPI aware. */ user32dll = LoadLibrary(L"user32.dll"); ex_SetProcessDPIAware = (SETPROCESSDPIAWARE) GetProcAddress(user32dll, "SetProcessDPIAware"); if (ex_SetProcessDPIAware != NIL) ex_SetProcessDPIAware(); /* Get default colors. */ UpdateColors(); /* Get mouse hover time and tolerance. */ SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &Setup::HoverTime, 0); SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH, 0, &Setup::HoverWidth, 0); SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT, 0, &Setup::HoverHeight, 0); return Success(); } S::Int S::Backends::BackendWin32::Deinit() { /* Free dynamically loaded user32 library. */ FreeLibrary(user32dll); /* Cleanup Windows sockets. */ WSACleanup(); /* Uninit COM library. */ OleUninitialize(); return Success(); } S::Void S::Backends::BackendWin32::UpdateColors() { /* Query dark mode and accent color on Windows 10. */ Bool darkModeEnabled = False; GUI::Color colorizationColor(-1); GUI::Color accentColor(-1); Bool accentColorPrevalence = False; HKEY key; if (RegOpenKey(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &key) == ERROR_SUCCESS) { DWORD value = 1; DWORD size = sizeof(value); if (RegQueryValueEx(key, L"AppsUseLightTheme", 0, NULL, (BYTE *) &value, &size) == ERROR_SUCCESS) darkModeEnabled = !value; RegCloseKey(key); } if (RegOpenKey(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\DWM", &key) == ERROR_SUCCESS) { DWORD value = 0; DWORD size = sizeof(value); if (RegQueryValueEx(key, L"ColorizationColor", 0, NULL, (BYTE *) &value, &size) == ERROR_SUCCESS) colorizationColor = GUI::Color((value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF); if (RegQueryValueEx(key, L"AccentColor", 0, NULL, (BYTE *) &value, &size) == ERROR_SUCCESS) accentColor = GUI::Color(value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF); if (RegQueryValueEx(key, L"ColorPrevalence", 0, NULL, (BYTE *) &value, &size) == ERROR_SUCCESS) accentColorPrevalence = value; RegCloseKey(key); } /* Set theme colors. */ if (darkModeEnabled) { Setup::BackgroundColor = GUI::Color(64, 64, 70); Setup::LightGrayColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6); Setup::ClientColor = GUI::Color(32, 32, 35); Setup::ClientTextColor = GUI::Color(255, 255, 255); Setup::DividerLightColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6); Setup::DividerDarkColor = GetSysColor(COLOR_3DSHADOW); Setup::TextColor = GUI::Color(245, 245, 245); Setup::InactiveTextColor = GUI::Color(160, 160, 160); Setup::LinkColor = GUI::Color(100, 160, 225); Setup::LinkHighlightColor = GUI::Color(100, 160, 225); } else { Setup::BackgroundColor = GetSysColor(COLOR_3DFACE); Setup::LightGrayColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6); Setup::ClientColor = GetSysColor(COLOR_WINDOW); Setup::ClientTextColor = GetSysColor(COLOR_WINDOWTEXT); Setup::DividerLightColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6); Setup::DividerDarkColor = GetSysColor(COLOR_3DSHADOW); Setup::TextColor = GetSysColor(COLOR_BTNTEXT); Setup::InactiveTextColor = GetSysColor(COLOR_GRAYTEXT); Setup::LinkColor = GetSysColor(COLOR_HOTLIGHT); Setup::LinkHighlightColor = GetSysColor(COLOR_HOTLIGHT); } /* Set accent colors. */ if (accentColor != GUI::Color(-1)) { Setup::HighlightColor = accentColor.Grayscale().GetRed() < 245 ? accentColor : GUI::Color(accentColor.GetRed() - accentColor.GetRed() * 0.15, accentColor.GetGreen() - accentColor.GetGreen() * 0.15, accentColor.GetBlue() - accentColor.GetBlue() * 0.15); Setup::HighlightTextColor = Setup::HighlightColor.Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255); if (darkModeEnabled) { Setup::GradientStartColor = GUI::Color(accentColor.GetRed() - accentColor.GetRed() * 0.45, accentColor.GetGreen() - accentColor.GetGreen() * 0.45, accentColor.GetBlue() - accentColor.GetBlue() * 0.45); Setup::GradientEndColor = GUI::Color(accentColor.GetRed() - accentColor.GetRed() * 0.30, accentColor.GetGreen() - accentColor.GetGreen() * 0.30, accentColor.GetBlue() - accentColor.GetBlue() * 0.30); Setup::GradientTextColor = GUI::Color(245, 245, 245); } else { Setup::GradientStartColor = GUI::Color(accentColor.GetRed() - accentColor.GetRed() * 0.15, accentColor.GetGreen() - accentColor.GetGreen() * 0.15, accentColor.GetBlue() - accentColor.GetBlue() * 0.15); Setup::GradientEndColor = GUI::Color(accentColor.GetRed() + (255 - accentColor.GetRed()) * 0.25, accentColor.GetGreen() + (255 - accentColor.GetGreen()) * 0.25, accentColor.GetBlue() + (255 - accentColor.GetBlue()) * 0.25); Setup::GradientTextColor = Setup::GradientStartColor.Average(Setup::GradientEndColor).Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255); } if (accentColorPrevalence) { Setup::TitlebarStartColor = accentColor; Setup::TitlebarEndColor = Setup::TitlebarStartColor; Setup::TitlebarTextColor = Setup::TitlebarStartColor.Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255); } else { Setup::TitlebarStartColor = Setup::GradientStartColor; Setup::TitlebarEndColor = Setup::GradientEndColor; Setup::TitlebarTextColor = Setup::GradientTextColor; } Setup::InactiveTitlebarStartColor = Setup::TitlebarStartColor.Grayscale(); Setup::InactiveTitlebarEndColor = Setup::TitlebarEndColor.Grayscale(); Setup::InactiveTitlebarTextColor = Setup::TitlebarTextColor.Grayscale(); } else if (colorizationColor != GUI::Color(-1)) { Setup::HighlightColor = colorizationColor.Grayscale().GetRed() < 245 ? colorizationColor : GUI::Color(colorizationColor.GetRed() - colorizationColor.GetRed() * 0.15, colorizationColor.GetGreen() - colorizationColor.GetGreen() * 0.15, colorizationColor.GetBlue() - colorizationColor.GetBlue() * 0.15); Setup::HighlightTextColor = Setup::HighlightColor.Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255); Setup::GradientStartColor = GUI::Color(colorizationColor.GetRed() - colorizationColor.GetRed() * 0.15, colorizationColor.GetGreen() - colorizationColor.GetGreen() * 0.15, colorizationColor.GetBlue() - colorizationColor.GetBlue() * 0.15); Setup::GradientEndColor = GUI::Color(colorizationColor.GetRed() + (255 - colorizationColor.GetRed()) * 0.25, colorizationColor.GetGreen() + (255 - colorizationColor.GetGreen()) * 0.25, colorizationColor.GetBlue() + (255 - colorizationColor.GetBlue()) * 0.25); Setup::GradientTextColor = Setup::GradientStartColor.Average(Setup::GradientEndColor).Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255); if (Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2)) { Setup::TitlebarStartColor = colorizationColor.Grayscale().GetRed() < 250 ? colorizationColor : GUI::Color(colorizationColor.GetRed() - colorizationColor.GetRed() * 0.02, colorizationColor.GetGreen() - colorizationColor.GetGreen() * 0.02, colorizationColor.GetBlue() - colorizationColor.GetBlue() * 0.02); Setup::TitlebarEndColor = Setup::TitlebarStartColor; Setup::TitlebarTextColor = Setup::TitlebarStartColor.Grayscale().GetRed() < 120 ? GUI::Color(245, 245, 245) : GUI::Color(0); Setup::InactiveTitlebarStartColor = GUI::Color(235, 235, 235); Setup::InactiveTitlebarEndColor = GUI::Color(235, 235, 235); Setup::InactiveTitlebarTextColor = GUI::Color(0); } else { Setup::TitlebarStartColor = Setup::GradientStartColor; Setup::TitlebarEndColor = Setup::GradientEndColor; Setup::TitlebarTextColor = Setup::TitlebarStartColor.Grayscale().GetRed() < 120 ? GUI::Color(245, 245, 245) : GUI::Color(0); Setup::InactiveTitlebarStartColor = Setup::TitlebarStartColor.Grayscale(); Setup::InactiveTitlebarEndColor = Setup::TitlebarEndColor.Grayscale(); Setup::InactiveTitlebarTextColor = Setup::TitlebarTextColor.Grayscale(); } } else { Setup::HighlightColor = GetSysColor(COLOR_HIGHLIGHT); Setup::HighlightTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT); Setup::GradientStartColor = GetSysColor(COLOR_ACTIVECAPTION); Setup::GradientEndColor = GetSysColor(COLOR_GRADIENTACTIVECAPTION); Setup::GradientTextColor = GetSysColor(COLOR_CAPTIONTEXT); Setup::TitlebarStartColor = GetSysColor(COLOR_ACTIVECAPTION); Setup::TitlebarEndColor = GetSysColor(COLOR_GRADIENTACTIVECAPTION); Setup::TitlebarTextColor = GetSysColor(COLOR_CAPTIONTEXT); Setup::InactiveTitlebarStartColor = GetSysColor(COLOR_INACTIVECAPTION); Setup::InactiveTitlebarEndColor = GetSysColor(COLOR_GRADIENTINACTIVECAPTION); Setup::InactiveTitlebarTextColor = GetSysColor(COLOR_INACTIVECAPTIONTEXT); } /* Set tooltip and link colors. */ Setup::TooltipColor = GetSysColor(COLOR_INFOBK); Setup::TooltipTextColor = GetSysColor(COLOR_INFOTEXT); } S::Bool S::Backends::BackendWin32::IsWindowsVersionAtLeast(UnsignedInt platformId, UnsignedInt majorVersion, UnsignedInt minorVersion) { static OSVERSIONINFO versionInfo = { 0 }; if (versionInfo.dwOSVersionInfoSize == 0) { versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&versionInfo); } if (versionInfo.dwPlatformId == platformId && ( versionInfo.dwMajorVersion > majorVersion || (versionInfo.dwMajorVersion == majorVersion && versionInfo.dwMinorVersion >= minorVersion))) return True; return False; } S::String S::Backends::BackendWin32::GetFullPathName(const String &shortPath) { static const String extendedPathPrefix = "\\\\?\\"; if (shortPath.StartsWith(extendedPathPrefix)) return shortPath; wchar_t buffer[MAX_EXT_PATH] = { 0 }; if (GetLongPathName(Directory::MakeExtendedPath(shortPath), buffer, MAX_EXT_PATH) == 0) return shortPath; return Directory::StripExtendedPathPrefix(buffer); } smooth-0.9.11~git20260403.0230c0da/classes/backends/xlib/000077500000000000000000000000001516402577000221255ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/backends/xlib/Makefile000066400000000000000000000012331516402577000235640ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags x11) MYCCOPTS += $(shell pkg-config --cflags gtk+-3.0) endif endif endif # Enter object files here: OBJECTS = ifeq ($(BUILD_XLIB),True) OBJECTS += backendxlib.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/backends/xlib/backendxlib.cpp000066400000000000000000000306121516402577000251010ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2025 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include using namespace X11; #ifndef GTK_STATE_FLAG_LINK # define GTK_STATE_FLAG_LINK GtkStateFlags(1 << 9) #endif static void toggleTimerInterrupts(bool allowed) { sigset_t ss; sigemptyset(&ss); sigaddset(&ss, SIGALRM); pthread_sigmask(allowed ? SIG_UNBLOCK : SIG_BLOCK, &ss, NIL); } static GdkRGBA get_gtk_color(GType type, const gchar *className, GtkStateFlags stateFlags, bool background) { /* Create dummy widget of requested type. */ GtkWidget *widget = NIL; if (type == GTK_TYPE_WINDOW) widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); else if (type == GTK_TYPE_TOOLTIP) widget = gtk_window_new(GTK_WINDOW_POPUP); else if (type == GTK_TYPE_BUTTON) widget = gtk_button_new(); else if (type == GTK_TYPE_TEXT_VIEW) widget = gtk_text_view_new(); else if (type == GTK_TYPE_LINK_BUTTON) widget = gtk_link_button_new(""); if (widget == NIL) return { 0, 0, 0, 0 }; /* Get GtkStyleContext to query color. */ GtkStyleContext *style = gtk_widget_get_style_context(widget); gtk_style_context_add_class(style, className); /* Query color from style context. */ GdkRGBA color; if (background) gtk_style_context_get_background_color(style, stateFlags, &color); else gtk_style_context_get_color(style, stateFlags, &color); g_object_ref_sink(widget); g_object_unref(widget); return color; } static S::GUI::Color get_kde_color(const S::String &category, const S::String &color) { S::String spec = S::Backends::BackendXLib::QueryKDESettings(S::String("Colors:").Append(category), color); const S::Array &values = spec.Explode(","); if (values.Length() != 3) return S::GUI::Color(); return S::GUI::Color(values.GetNth(0).ToInt(), values.GetNth(1).ToInt(), values.GetNth(2).ToInt()); } S::Backends::Backend *CreateBackendXLib() { return new S::Backends::BackendXLib(); } S::Int backendXLibTmp = S::Backends::Backend::AddBackend(&CreateBackendXLib); Display *S::Backends::BackendXLib::display = NIL; XIM S::Backends::BackendXLib::im = NIL; S::Backends::BackendXLib::BackendXLib() { type = BACKEND_XLIB; } S::Backends::BackendXLib::~BackendXLib() { } S::Int S::Backends::BackendXLib::Init() { XInitThreads(); /* Open display. */ const char *displayId = getenv("DISPLAY"); if (displayId != NIL) { display = XOpenDisplay(NIL); if (display == NIL) { fprintf(stderr, "Error: Unable to open display at %s.\n", displayId); return Error(); } /* Init the GTK with SIGALRM signals disabled to make * threads created by gtk_init inherit this SIGMASK. */ toggleTimerInterrupts(false); gtk_init(NULL, NULL); /* Get default colors. */ UpdateColors(); /* Set locale and open input method. */ setlocale(LC_ALL, ""); XSetLocaleModifiers(""); im = XOpenIM(display, NIL, NIL, NIL); } return Success(); } S::Int S::Backends::BackendXLib::Deinit() { if (im != NIL) XCloseIM(im); if (display != NIL) XCloseDisplay(display); toggleTimerInterrupts(true); return Success(); } S::Void S::Backends::BackendXLib::UpdateColors() { /* Check desktop environment. */ String desktop = getenv("XDG_CURRENT_DESKTOP"); const Array &IDs = desktop.Explode(":"); foreach (const String &ID, IDs) { if (ID == "KDE" && UpdateColorsKDE()) return; } UpdateColorsGnome(); } S::Bool S::Backends::BackendXLib::UpdateColorsGnome() { /* Query UI colors defined in GTK theme. */ GdkRGBA backgroundColor = get_gtk_color(GTK_TYPE_WINDOW, GTK_STYLE_CLASS_BACKGROUND, GTK_STATE_FLAG_NORMAL, true); GdkRGBA textColor = get_gtk_color(GTK_TYPE_BUTTON, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, false); if (gdk_rgba_equal(&backgroundColor, &textColor)) return False; GdkRGBA clientColor = get_gtk_color(GTK_TYPE_TEXT_VIEW, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, true); GdkRGBA clientTextColor = get_gtk_color(GTK_TYPE_TEXT_VIEW, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, false); GdkRGBA highlightColor = get_gtk_color(GTK_TYPE_TEXT_VIEW, GTK_STYLE_CLASS_VIEW, GtkStateFlags(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), true); GdkRGBA highlightTextColor = get_gtk_color(GTK_TYPE_TEXT_VIEW, GTK_STYLE_CLASS_VIEW, GtkStateFlags(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), false); GdkRGBA tooltipColor = get_gtk_color(GTK_TYPE_TOOLTIP, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, true); GdkRGBA tooltipTextColor = get_gtk_color(GTK_TYPE_TOOLTIP, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, false); GdkRGBA linkColor = get_gtk_color(GTK_TYPE_LINK_BUTTON, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_LINK, false); GdkRGBA linkHighlightColor = get_gtk_color(GTK_TYPE_LINK_BUTTON, GTK_STYLE_CLASS_VIEW, GtkStateFlags(GTK_STATE_FLAG_LINK | GTK_STATE_FLAG_PRELIGHT), false); /* Convert to smooth colors. */ Setup::BackgroundColor = GUI::Color(255 * backgroundColor.red, 255 * backgroundColor.green, 255 * backgroundColor.blue); Setup::LightGrayColor = GUI::Color(255 * (backgroundColor.red + (1.0 - backgroundColor.red) * 0.6), 255 * (backgroundColor.green + (1.0 - backgroundColor.green) * 0.6), 255 * (backgroundColor.blue + (1.0 - backgroundColor.blue) * 0.6)); Setup::ClientColor = GUI::Color(255 * clientColor.red, 255 * clientColor.green, 255 * clientColor.blue); Setup::ClientTextColor = GUI::Color(255 * clientTextColor.red, 255 * clientTextColor.green, 255 * clientTextColor.blue); Setup::DividerLightColor = GUI::Color(255 * (backgroundColor.red + (1.0 - backgroundColor.red) * 0.6), 255 * (backgroundColor.green + (1.0 - backgroundColor.green) * 0.6), 255 * (backgroundColor.blue + (1.0 - backgroundColor.blue) * 0.6)); Setup::DividerDarkColor = GUI::Color(255 * backgroundColor.red * 0.7, 255 * backgroundColor.green * 0.7, 255 * backgroundColor.blue * 0.7); Setup::TextColor = GUI::Color(255 * textColor.red, 255 * textColor.green, 255 * textColor.blue); Setup::InactiveTextColor = Setup::TextColor.Average(Setup::BackgroundColor); Setup::HighlightColor = GUI::Color(255 * highlightColor.red, 255 * highlightColor.green, 255 * highlightColor.blue); Setup::HighlightTextColor = GUI::Color(255 * highlightTextColor.red, 255 * highlightTextColor.green, 255 * highlightTextColor.blue); Setup::GradientStartColor = GUI::Color(255 * (highlightColor.red - highlightColor.red * 0.15), 255 * (highlightColor.green - highlightColor.green * 0.15), 255 * (highlightColor.blue - highlightColor.blue * 0.15)); Setup::GradientEndColor = GUI::Color(255 * (highlightColor.red + (1.0 - highlightColor.red) * 0.15), 255 * (highlightColor.green + (1.0 - highlightColor.green) * 0.15), 255 * (highlightColor.blue + (1.0 - highlightColor.blue) * 0.15)); Setup::GradientTextColor = GUI::Color(255 * highlightTextColor.red, 255 * highlightTextColor.green, 255 * highlightTextColor.blue); Setup::TooltipColor = GUI::Color(255 * tooltipColor.red, 255 * tooltipColor.green, 255 * tooltipColor.blue); Setup::TooltipTextColor = GUI::Color(255 * tooltipTextColor.red, 255 * tooltipTextColor.green, 255 * tooltipTextColor.blue); if (GUI::Color(255 * linkColor.red, 255 * linkColor.green, 255 * linkColor.blue) != Setup::TextColor) { Setup::LinkColor = GUI::Color(255 * linkColor.red, 255 * linkColor.green, 255 * linkColor.blue); Setup::LinkHighlightColor = GUI::Color(255 * linkHighlightColor.red, 255 * linkHighlightColor.green, 255 * linkHighlightColor.blue); } return True; } S::Bool S::Backends::BackendXLib::UpdateColorsKDE() { GUI::Color backgroundColor = get_kde_color("Window", "BackgroundNormal"); GUI::Color textColor = get_kde_color("Window", "ForegroundNormal"); if (backgroundColor == textColor) return False; Setup::BackgroundColor = backgroundColor; Setup::TextColor = textColor; Setup::InactiveTextColor = get_kde_color("Window", "ForegroundInactive"); if (Setup::BackgroundColor.Grayscale() < Setup::TextColor.Grayscale()) { GUI::Color backgroundAlternate = get_kde_color("Window", "BackgroundAlternate"); if (backgroundAlternate.Grayscale() > Setup::BackgroundColor.Grayscale()) Setup::BackgroundColor = backgroundAlternate; } Setup::LightGrayColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6); Setup::ClientColor = get_kde_color("View", "BackgroundNormal"); Setup::ClientTextColor = get_kde_color("View", "ForegroundNormal"); Setup::DividerLightColor = Setup::LightGrayColor; Setup::DividerDarkColor = GUI::Color(Setup::BackgroundColor.GetRed() * 0.7, Setup::BackgroundColor.GetGreen() * 0.7, Setup::BackgroundColor.GetBlue() * 0.7); Setup::HighlightColor = get_kde_color("Selection", "BackgroundNormal"); Setup::HighlightTextColor = get_kde_color("Selection", "ForegroundNormal"); Setup::GradientStartColor = GUI::Color(Setup::HighlightColor.GetRed() * 0.75, Setup::HighlightColor.GetGreen() * 0.75, Setup::HighlightColor.GetBlue() * 0.75); Setup::GradientEndColor = GUI::Color(Setup::HighlightColor.GetRed() + (255 - Setup::HighlightColor.GetRed()) * 0.15, Setup::HighlightColor.GetGreen() + (255 - Setup::HighlightColor.GetGreen()) * 0.15, Setup::HighlightColor.GetBlue() + (255 - Setup::HighlightColor.GetBlue()) * 0.15); Setup::GradientTextColor = Setup::HighlightTextColor; Setup::TooltipColor = get_kde_color("Tooltip", "BackgroundNormal"); Setup::TooltipTextColor = get_kde_color("Tooltip", "ForegroundNormal"); Setup::LinkColor = get_kde_color("Window", "ForegroundLink"); Setup::LinkHighlightColor = get_kde_color("Window", "ForegroundActive"); return True; } Display *S::Backends::BackendXLib::GetDisplay() { return display; } XIM S::Backends::BackendXLib::GetIM() { return im; } S::String S::Backends::BackendXLib::FindExecutable(const String &executable) { /* Search the path for executable. */ String path = getenv("PATH"); const Array &paths = path.Explode(":"); foreach (const String &path, paths) { /* Check for executable in this path. */ File file(String(path).Append("/").Append(executable)); if (file.Exists()) return file; } return NIL; } S::String S::Backends::BackendXLib::QueryGSettings(const String &schema, const String &key) { static String gsettings = FindExecutable("gsettings"); if (gsettings == NIL) return NIL; /* Execute gsettings to query value. */ FILE *pstdin = popen(String(gsettings).Append(" get ").Append(schema).Append(" ").Append(key), "r"); if (pstdin != NIL) { char value[256]; if (fgets(value, 256, pstdin) != NIL) { pclose(pstdin); return value; } pclose(pstdin); } return NIL; } S::String S::Backends::BackendXLib::QueryKDESettings(const String &category, const String &key) { File kdeConfig("kdeglobals", System::System::GetApplicationDataDirectory()); if (!kdeConfig.Exists()) return NIL; IO::InStream in(IO::STREAM_FILE, kdeConfig, IO::IS_READ); /* Find category header. */ while (in.GetPos() < in.Size()) { String line = in.InputLine(); if (line == String("[").Append(category).Append("]")) break; } /* Find key. */ while (in.GetPos() < in.Size()) { String line = in.InputLine(); if ( line.StartsWith("[")) break; if (!line.StartsWith(key.Append("="))) continue; return line.Tail(line.Length() - line.Find("=") - 1); } return NIL; } S::String S::Backends::BackendXLib::QueryXfConf(const String &channel, const String &property) { static String xfconfquery = FindExecutable("xfconf-query"); if (xfconfquery == NIL) return NIL; /* Execute xfconf-query to query value. */ FILE *pstdin = popen(String(xfconfquery).Append(" -c ").Append(channel).Append(" -p ").Append(property), "r"); if (pstdin != NIL) { char value[256]; if (fgets(value, 256, pstdin) != NIL) { pclose(pstdin); return value; } pclose(pstdin); } return NIL; } smooth-0.9.11~git20260403.0230c0da/classes/basic/000077500000000000000000000000001516402577000204765ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/basic/Makefile000066400000000000000000000004701516402577000221370ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. # Enter object files here: OBJECTS = object.o objecttype.o setup.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/basic/object.cpp000066400000000000000000000077521516402577000224630ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::Object::classID = S::Object::RequestClassID(); S::Short S::Object::nextClassID = 0; S::Int S::Object::nextObjectHandle = 0; S::Array S::Object::objects; S::Array S::Object::deletable; S::System::Timer *S::Object::cleanupTimer = NIL; S::Object::Object() : type(this) { /* Enable R/W locking for object lists. */ if (objects.Length() == 0) { objects.EnableLocking(); deletable.EnableLocking(); } type = classID; handle = RequestObjectHandle(); name = NIL; lockingEnabled = False; isDeletable = False; isObjectInUse = 0; flags = 0; objects.Add(this, handle); /* Create periodical cleanup timer if we * just created the first object. */ if (objects.Length() == 1) { cleanupTimer = new System::Timer(); cleanupTimer->onInterval.Connect(&Object::ObjectCleanup); cleanupTimer->Start(1000); } } S::Object::~Object() { /* Try to remove ourself from the object list * as DeleteObject might not have been called. */ if (!isDeletable) objects.Remove(handle); /* Free periodical cleanup timer if the timer * itself is the only remaining object. */ if (objects.Length() == 1) { cleanupTimer->Stop(); DeleteObject(cleanupTimer); } /* Delete name string if it was created. */ if (name != NIL) delete name; } S::Int S::Object::EnableLocking(Bool enable) { lockingEnabled = enable; return Success(); } S::Int S::Object::GetNOfObjects() { return objects.Length(); } S::Object *S::Object::GetNthObject(Int n) { return objects.GetNth(n); } S::Object *S::Object::GetObject(Int objectHandle, Short objectType) { Object *object = objects.Get(objectHandle); if (object == NIL) return NIL; if (object->GetObjectType() == objectType) return object; else return NIL; } S::Object *S::Object::GetObject(const String &objectName) { for (Int i = 0; i < GetNOfObjects(); i++) { Object *object = GetNthObject(i); if (object->name != NIL && *(object->name) == objectName) return object; } return NIL; } S::Int S::Object::SetName(const String &nName) { if (GetObject(nName) != NIL) return Error(); if (name == NIL) name = new String(); *name = nName; return Success(); } const S::String &S::Object::GetName() const { static String prefix = "Object::"; if (name == NIL) name = new String(String(prefix).Append(String::FromInt(handle))); return *name; } S::Short S::Object::RequestClassID() { return nextClassID++; } S::Int S::Object::RequestObjectHandle() { if (initializing) return nextObjectHandle++; else return Threads::Access::Increment(nextObjectHandle) - 1; } S::Int S::Object::DeleteObject(Object *object) { if (object == NIL || objects.Get(object->handle) == NIL) return Error(); /* Notify object that it will be deleted soon. */ object->EnqueueForDeletion(); object->isDeletable = True; if (!object->IsObjectInUse()) { /* Delete object immediately if * it is not currently in use. */ objects.Remove(object->handle); delete object; } else { /* Remove object from object list and add * it to the list of objects to delete. */ objects.Remove(object->handle); deletable.Add(object, object->handle); } return Success(); } S::Void S::Object::ObjectCleanup() { /* Loop through all deletable objects... */ for (Int i = 0; i < deletable.Length(); i++) { Object *object = deletable.GetNth(i); if (object->IsObjectInUse()) continue; deletable.RemoveNth(i--); delete object; } } smooth-0.9.11~git20260403.0230c0da/classes/basic/objecttype.cpp000066400000000000000000000015261516402577000233560ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2010 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::ObjectType::ObjectType(Object *iObject) { object = iObject; type = Object::classID; } S::ObjectType::ObjectType(const ObjectType &objectType) { object = objectType.object; type = objectType.type; } S::Bool S::ObjectType::operator ==(Short objType) const { return (type == objType) ? True : object->IsTypeCompatible(objType); } smooth-0.9.11~git20260403.0230c0da/classes/basic/setup.cpp000066400000000000000000000043701516402577000223460ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include /* Init color constant with default values. */ S::GUI::Color S::Setup::BackgroundColor(240, 240, 240); S::GUI::Color S::Setup::ClientColor(255, 255, 255); S::GUI::Color S::Setup::ClientTextColor(0, 0, 0); S::GUI::Color S::Setup::LightGrayColor(248, 248, 248); S::GUI::Color S::Setup::DividerLightColor(237, 236, 232); S::GUI::Color S::Setup::DividerDarkColor(128, 128, 128); S::GUI::Color S::Setup::TextColor(0, 0, 0); S::GUI::Color S::Setup::InactiveTextColor(128, 128, 128); S::GUI::Color S::Setup::HighlightColor(55, 115, 215); S::GUI::Color S::Setup::HighlightTextColor(255, 255, 255); S::GUI::Color S::Setup::GradientStartColor(10, 36, 106); S::GUI::Color S::Setup::GradientEndColor(166, 202, 240); S::GUI::Color S::Setup::GradientTextColor(255, 255, 255); S::GUI::Color S::Setup::TitlebarStartColor(10, 36, 106); S::GUI::Color S::Setup::TitlebarEndColor(166, 202, 240); S::GUI::Color S::Setup::TitlebarTextColor(255, 255, 255); S::GUI::Color S::Setup::InactiveTitlebarStartColor(128, 128, 128); S::GUI::Color S::Setup::InactiveTitlebarEndColor(192, 192, 192); S::GUI::Color S::Setup::InactiveTitlebarTextColor(212, 208, 200); S::GUI::Color S::Setup::TooltipColor(255, 255, 225); S::GUI::Color S::Setup::TooltipTextColor(0, 0, 0); S::GUI::Color S::Setup::LinkColor(0, 0, 225); S::GUI::Color S::Setup::LinkHighlightColor(0, 128, 225); #ifdef __WIN32__ S::Bool S::Setup::useIconv = S::False; #else S::Bool S::Setup::useIconv = S::True; #endif S::Float S::Setup::FontSize = 1.00; S::Bool S::Setup::rightToLeft = S::False; S::Int S::Setup::HoverTime = 400; S::Int S::Setup::HoverWidth = 4; S::Int S::Setup::HoverHeight = 4; S::Setup::Setup() { } S::Setup::Setup(const Setup &) { } S::Setup::Setup(const Setup *) { } smooth-0.9.11~git20260403.0230c0da/classes/errors/000077500000000000000000000000001516402577000207315ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/errors/Makefile000066400000000000000000000007451516402577000223770ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. # Enter object files here: OBJECTS = error.o success.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,fs) ALLCMD2 = $(call makein,misc) CLEANCMD1 = $(call cleanin,fs) CLEANCMD2 = $(call cleanin,misc) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/errors/error.cpp000077500000000000000000000014461516402577000225760ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::String S::Errors::Error::ToString() const { return "Unknown error"; } S::Bool S::Errors::Error::operator ==(const Error &error) const { if (code == error.code) return True; else return False; } S::Bool S::Errors::Error::operator !=(const Error &error) const { return !(*this == error); } smooth-0.9.11~git20260403.0230c0da/classes/errors/fs/000077500000000000000000000000001516402577000213415ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/errors/fs/Makefile000066400000000000000000000004701516402577000230020ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = endoffile.o filenotfound.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/errors/fs/endoffile.cpp000077500000000000000000000011751516402577000240070ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Errors::EndOfFile::EndOfFile() { code = -100; } S::String S::Errors::EndOfFile::ToString() const { return "End of file"; } smooth-0.9.11~git20260403.0230c0da/classes/errors/fs/filenotfound.cpp000077500000000000000000000012141516402577000245420ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Errors::FileNotFound::FileNotFound() { code = -101; } S::String S::Errors::FileNotFound::ToString() const { return "File not found"; } smooth-0.9.11~git20260403.0230c0da/classes/errors/misc/000077500000000000000000000000001516402577000216645ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/errors/misc/Makefile000066400000000000000000000004601516402577000233240ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = permissiondenied.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/errors/misc/permissiondenied.cpp000077500000000000000000000012371516402577000257370ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Errors::PermissionDenied::PermissionDenied() { code = -2; } S::String S::Errors::PermissionDenied::ToString() const { return "Permission denied"; } smooth-0.9.11~git20260403.0230c0da/classes/errors/success.cpp000077500000000000000000000011051516402577000231050ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::String S::Errors::Success::ToString() const { return "Operation successful"; } smooth-0.9.11~git20260403.0230c0da/classes/files/000077500000000000000000000000001516402577000205175ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/files/Makefile000066400000000000000000000004551516402577000221630ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. # Enter object files here: OBJECTS = directory.o file.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/files/directory.cpp000066400000000000000000000262641516402577000232410ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Define to get 64 bit stat call. */ #ifndef __WIN32__ # define _FILE_OFFSET_BITS 64 #endif #include #ifdef __WIN32__ # include # include #else # include # include # include # include # include # ifndef PATH_MAX # define PATH_MAX 32768 # endif # ifndef GLOB_ONLYDIR # define GLOB_ONLYDIR 0 # endif #endif static const S::String &kDelimiter = S::Directory::GetDirectoryDelimiter(); static const S::String kSlash = "/"; static const S::String kBackslash = "\\"; static const S::String kUncPrefix = "\\\\"; static const S::String kDot = "."; static const S::String kDots = ".."; static const S::String kTilde = "~"; static const S::String kDotElement = S::String(kDelimiter).Append(kDot).Append(kDelimiter); static const S::String kDotsElement = S::String(kDelimiter).Append(kDots).Append(kDelimiter); char *S::Directory::directoryDelimiter = NIL; S::Directory::Directory() { } S::Directory::Directory(const String &iDirName, const String &iDirPath) { dirName = iDirName; dirPath = iDirPath; #ifdef __WIN32__ if (dirName.Contains(kSlash)) dirName.Replace(kSlash, kDelimiter); if (dirPath.Contains(kSlash)) dirPath.Replace(kSlash, kDelimiter); #else if (dirName.Contains(kBackslash)) dirName.Replace(kBackslash, kDelimiter); if (dirPath.Contains(kBackslash)) dirPath.Replace(kBackslash, kDelimiter); #endif if (dirName != NIL && dirPath == NIL) { #ifdef __WIN32__ if (dirName.StartsWith(kDelimiter) && !dirName.StartsWith(kUncPrefix)) dirName = String(Directory::GetActiveDirectory()).Head(2).Append(dirName); #endif #ifdef __WIN32__ if (dirName[1] == ':' || dirName.StartsWith(kUncPrefix)) #else if (dirName.StartsWith(kDelimiter) || dirName.StartsWith(kTilde)) #endif { dirPath = dirName; dirName = NIL; } else { dirPath = String(Directory::GetActiveDirectory()).Append(kDelimiter).Append(dirName); dirName = NIL; } } if (dirName == NIL) { if (dirPath.EndsWith(kDelimiter)) dirPath[dirPath.Length() - 1] = 0; Int lastBS = dirPath.FindLast(kDelimiter); if (lastBS >= 0) { dirName = dirPath.Tail(dirPath.Length() - lastBS - 1); dirPath[lastBS] = 0; } } /* Replace ./ elements. */ if (!dirPath.EndsWith(kDelimiter)) dirPath.Append(kDelimiter); if (dirPath.Contains(kDotElement)) dirPath.Replace(kDotElement, kDelimiter); if (dirPath.StartsWith(String(kDot).Append(kDelimiter))) dirPath = String(Directory::GetActiveDirectory()).Append(dirPath.Tail(dirPath.Length() - 2)); /* Replace ../ elements. */ while (dirPath.Contains(kDotsElement)) { Int upPos = dirPath.Find(kDotsElement); Int prePos = dirPath.Head(upPos).FindLast(kDelimiter); dirPath.Replace(dirPath.SubString(prePos, upPos - prePos + 3), String()); } if (dirPath.EndsWith(kDelimiter)) dirPath[dirPath.Length() - 1] = 0; } S::Directory::Directory(const Directory &iDirectory) { *this = iDirectory; } S::Directory::~Directory() { } S::Directory &S::Directory::operator =(const Directory &nDirectory) { if (&nDirectory == this) return *this; dirName = nDirectory.dirName; dirPath = nDirectory.dirPath; return *this; } S::Directory::operator S::String() const { if (dirName == NIL) return dirPath; return String(dirPath).Append(kDelimiter).Append(dirName); } const S::String &S::Directory::GetDirectoryName() const { return dirName; } const S::String &S::Directory::GetDirectoryPath() const { return dirPath; } const S::Array &S::Directory::GetFiles() const { return GetFilesByPattern("*"); } const S::Array &S::Directory::GetDirectories() const { return GetDirectoriesByPattern("*"); } const S::Array &S::Directory::GetFilesByPattern(const String &pattern) const { files.RemoveAll(); #ifdef __WIN32__ WIN32_FIND_DATA findData; HANDLE handle = FindFirstFile(MakeExtendedPath(*this).Append(kBackslash).Append(pattern), &findData); Bool success = (handle != INVALID_HANDLE_VALUE); while (success) { if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) files.Add(File(findData.cFileName, *this)); success = FindNextFile(handle, &findData); } FindClose(handle); #else String path = String(*this).Replace("*", "\\*").Replace("?", "\\?"). Replace("[", "\\[").Replace("]", "\\]"); glob_t fileData = { 0 }; if (glob(path.Append(kSlash).Append(pattern).ConvertTo("UTF-8"), GLOB_MARK, NIL, &fileData) == 0) { String::InputFormat inputFormat("UTF-8"); for (size_t i = 0; i < fileData.gl_pathc; i++) { if (!String(fileData.gl_pathv[i]).EndsWith(kSlash)) files.Add(File(fileData.gl_pathv[i])); } globfree(&fileData); } #endif return files; } const S::Array &S::Directory::GetDirectoriesByPattern(const String &pattern) const { directories.RemoveAll(); #ifdef __WIN32__ WIN32_FIND_DATA findData; HANDLE handle = FindFirstFile(MakeExtendedPath(*this).Append(kBackslash).Append(pattern), &findData); Bool success = (handle != INVALID_HANDLE_VALUE); while (success) { if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && String(findData.cFileName) != kDot && String(findData.cFileName) != kDots) directories.Add(Directory(findData.cFileName, *this)); success = FindNextFile(handle, &findData); } FindClose(handle); #else String path = String(*this).Replace("*", "\\*").Replace("?", "\\?"). Replace("[", "\\[").Replace("]", "\\]"); glob_t fileData = { 0 }; if (glob(path.Append(kSlash).Append(pattern).ConvertTo("UTF-8"), GLOB_MARK | GLOB_ONLYDIR, NIL, &fileData) == 0) { String::InputFormat inputFormat("UTF-8"); for (size_t i = 0; i < fileData.gl_pathc; i++) { if (String(fileData.gl_pathv[i]).EndsWith(kSlash)) directories.Add(Directory(fileData.gl_pathv[i])); } globfree(&fileData); } #endif return directories; } S::DateTime S::Directory::GetCreateTime() const { DateTime dateTime; if (!Exists()) return dateTime; #ifdef __WIN32__ WIN32_FIND_DATA findData; HANDLE handle = FindFirstFile(MakeExtendedPath(*this), &findData); FindClose(handle); SYSTEMTIME time; FileTimeToSystemTime(&findData.ftCreationTime, &time); dateTime.SetYMD(time.wYear, time.wMonth, time.wDay); dateTime.SetHMS(time.wHour, time.wMinute, time.wSecond); #endif return dateTime; } S::Bool S::Directory::Exists() const { #ifdef __WIN32__ /* Check if root directory of a drive */ if (dirPath[dirPath.Length() - 1] == ':' && dirName == NIL) { DWORD drives = GetLogicalDrives(); if ((drives >> (dirPath.ToUpper()[0] - 'A')) & 1) return True; else return False; } WIN32_FIND_DATA findData; HANDLE handle = FindFirstFile(MakeExtendedPath(*this), &findData); if (handle == INVALID_HANDLE_VALUE) return False; FindClose(handle); if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) return False; #else struct stat info; if (stat(String(*this).ConvertTo("UTF-8"), &info) != 0) return False; if (!S_ISDIR(info.st_mode)) return False; #endif return True; } S::Int S::Directory::Create() { if (Exists()) return Success(); Bool result = False; String directory = *this; for (Int i = 1; i <= directory.Length(); i++) { if (directory[i] == '\\' || directory[i] == '/' || directory[i] == 0) { String path = directory.Head(i); #ifdef __WIN32__ result = CreateDirectory(MakeExtendedPath(path), NIL); #else if (mkdir(path.ConvertTo("UTF-8"), 0777) == 0) result = True; else result = False; #endif } } if (result == False) return Error(); else return Success(); } S::Int S::Directory::Copy(const Directory &destination) { return Error(); } S::Int S::Directory::Move(const Directory &destination) { if (!Exists()) return Error(); #ifdef __WIN32__ Bool result = MoveFile(MakeExtendedPath(*this), MakeExtendedPath(destination)); #else Bool result = (rename(String(*this).ConvertTo("UTF-8"), String(destination).ConvertTo("UTF-8")) == 0); #endif if (result == False) return Error(); else return Success(); } S::Int S::Directory::Delete() { #ifdef __WIN32__ Bool result = RemoveDirectory(MakeExtendedPath(*this)); #else Bool result = (rmdir(String(*this).ConvertTo("UTF-8")) == 0); #endif if (result == False) return Error(); else return Success(); } S::Int S::Directory::Empty() { #ifdef __WIN32__ WIN32_FIND_DATA findData; HANDLE handle = FindFirstFile(MakeExtendedPath(*this).Append("\\*"), &findData); if (handle == INVALID_HANDLE_VALUE) return Error(); do { if (String(findData.cFileName) == kDot || String(findData.cFileName) == kDots) continue; if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { Directory dir(findData.cFileName, *this); dir.Empty(); dir.Delete(); } else { File(findData.cFileName, *this).Delete(); } } while (FindNextFile(handle, &findData)); FindClose(handle); #endif return Success(); } const char *S::Directory::GetDirectoryDelimiter() { if (directoryDelimiter == NIL) { #ifdef __WIN32__ directoryDelimiter = (char *) "\\"; #else directoryDelimiter = (char *) "/"; #endif } return directoryDelimiter; } const char *S::Directory::GetUnicodePathPrefix(const String &path) { #ifdef __WIN32__ static const char *unicodePathPrefix = "\\\\?\\"; if (path.StartsWith(kUncPrefix)) return ""; return unicodePathPrefix; #endif return ""; } S::String S::Directory::MakeExtendedPath(const String &path) { #ifdef __WIN32__ static const String extendedPathPrefix = "\\\\?\\"; static const String uncPathPrefix = "\\\\?\\UNC\\"; if (!path.StartsWith(extendedPathPrefix)) { if (path.StartsWith(kUncPrefix)) return String(uncPathPrefix).Append(path.Tail(path.Length() - 2)); return String(extendedPathPrefix).Append(path); } #endif return path; } S::String S::Directory::StripExtendedPathPrefix(const String &path) { #ifdef __WIN32__ static const String extendedPathPrefix = "\\\\?\\"; static const String uncPathPrefix = "\\\\?\\UNC\\"; if (path.StartsWith(extendedPathPrefix)) { if (path.StartsWith(uncPathPrefix)) return String(kUncPrefix).Append(path.Tail(path.Length() - uncPathPrefix.Length())); return path.Tail(path.Length() - extendedPathPrefix.Length()); } #endif return path; } S::Directory S::Directory::GetActiveDirectory() { #ifdef __WIN32__ Buffer buffer(32768 + 1); GetCurrentDirectory(buffer.Size(), buffer); String dir = (wchar_t *) buffer; #else Buffer buffer(PATH_MAX + 1); String dir; if (getcwd(buffer, buffer.Size()) != NIL) dir = buffer; #endif return Directory(NIL, dir); } S::Int S::Directory::SetActiveDirectory(const Directory &directory) { #ifdef __WIN32__ Bool result = SetCurrentDirectory(MakeExtendedPath(directory).Append(kBackslash)); #else Bool result = (chdir(String(directory).ConvertTo("UTF-8")) == 0); #endif if (result == False) return Error(); else return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/files/file.cpp000066400000000000000000000254361516402577000221540ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Define to get 64 bit stat call. */ #ifndef __WIN32__ # define _FILE_OFFSET_BITS 64 #endif #include #include #include #ifdef __WIN32__ # include #else # include # include # include # include #endif namespace smooth { #ifdef __WIN32__ typedef FILETIME FileTime; DateTime FileTimeToDateTime(const FileTime &fileTime) { SYSTEMTIME utc, time; FileTimeToSystemTime(&fileTime, &utc); SystemTimeToTzSpecificLocalTime(NIL, &utc, &time); DateTime dateTime; dateTime.SetYMD(time.wYear, time.wMonth, time.wDay); dateTime.SetHMS(time.wHour, time.wMinute, time.wSecond); return dateTime; } FileTime DateTimeToFileTime(const DateTime &dateTime) { SYSTEMTIME time, utc; memset(&time, 0, sizeof(time)); time.wYear = dateTime.GetYear(); time.wMonth = dateTime.GetMonth(); time.wDay = dateTime.GetDay(); time.wHour = dateTime.GetHour(); time.wMinute = dateTime.GetMinute(); time.wSecond = dateTime.GetSecond(); FileTime fileTime; TzSpecificLocalTimeToSystemTime(NIL, &time, &utc); SystemTimeToFileTime(&utc, &fileTime); return fileTime; } Bool GetFileTime(const File &file, FileTime *cTime, FileTime *aTime, FileTime *wTime) { if (!file.Exists()) return False; HANDLE handle = CreateFile(Directory::MakeExtendedPath(file), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NIL); ::GetFileTime(handle, cTime, aTime, wTime); CloseHandle(handle); return True; } Bool SetFileTime(const File &file, FileTime *cTime, FileTime *aTime, FileTime *wTime) { if (!file.Exists()) return False; HANDLE handle = CreateFile(Directory::MakeExtendedPath(file), GENERIC_WRITE, 0, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NIL); ::SetFileTime(handle, cTime, aTime, wTime); CloseHandle(handle); return True; } #else typedef time_t FileTime; DateTime FileTimeToDateTime(const FileTime &fileTime) { tm time; localtime_r(&fileTime, &time); DateTime dateTime; dateTime.SetYMD(time.tm_year + 1900, time.tm_mon + 1, time.tm_mday); dateTime.SetHMS(time.tm_hour, time.tm_min, time.tm_sec); return dateTime; } FileTime DateTimeToFileTime(const DateTime &dateTime) { tm time; memset(&time, 0, sizeof(time)); time.tm_year = dateTime.GetYear() - 1900; time.tm_mon = dateTime.GetMonth() - 1; time.tm_mday = dateTime.GetDay(); time.tm_hour = dateTime.GetHour(); time.tm_min = dateTime.GetMinute(); time.tm_sec = dateTime.GetSecond(); time.tm_isdst = -1; return mktime(&time); } Bool GetFileTime(const File &file, FileTime *cTime, FileTime *aTime, FileTime *wTime) { if (!file.Exists()) return False; struct stat info; if (stat(String(file).ConvertTo("UTF-8"), &info) != 0) return False; if (cTime != NIL) *cTime = info.st_mtime; if (aTime != NIL) *aTime = info.st_atime; if (wTime != NIL) *wTime = info.st_mtime; return True; } Bool SetFileTime(const File &file, FileTime *cTime, FileTime *aTime, FileTime *wTime) { if (!file.Exists()) return False; struct stat info; struct utimbuf times; if (stat(String(file).ConvertTo("UTF-8"), &info) != 0) return False; times.actime = info.st_atime; times.modtime = info.st_mtime; if (cTime != NIL) times.modtime = *cTime; if (aTime != NIL) times.actime = *aTime; if (wTime != NIL) times.modtime = *wTime; if (utime(String(file).ConvertTo("UTF-8"), ×) != 0) return False; return True; } #endif }; static const S::String &kDelimiter = S::Directory::GetDirectoryDelimiter(); static const S::String kSlash = "/"; static const S::String kBackslash = "\\"; static const S::String kUncPrefix = "\\\\"; static const S::String kDot = "."; static const S::String kDots = ".."; static const S::String kTilde = "~"; static const S::String kDotElement = S::String(kDelimiter).Append(kDot).Append(kDelimiter); static const S::String kDotsElement = S::String(kDelimiter).Append(kDots).Append(kDelimiter); S::File::File() { } S::File::File(const String &iFileName, const String &iFilePath) { fileName = iFileName; filePath = iFilePath; #ifdef __WIN32__ if (fileName.Contains(kSlash)) fileName.Replace(kSlash, kDelimiter); if (filePath.Contains(kSlash)) filePath.Replace(kSlash, kDelimiter); #else if (fileName.Contains(kBackslash)) fileName.Replace(kBackslash, kDelimiter); if (filePath.Contains(kBackslash)) filePath.Replace(kBackslash, kDelimiter); #endif if (fileName != NIL && filePath == NIL) { #ifdef __WIN32__ if (fileName.StartsWith(kDelimiter) && !fileName.StartsWith(kUncPrefix)) fileName = String(Directory::GetActiveDirectory()).Head(2).Append(fileName); #endif #ifdef __WIN32__ if (fileName[1] == ':' || fileName.StartsWith(kUncPrefix)) #else if (fileName.StartsWith(kDelimiter) || fileName.StartsWith(kTilde)) #endif { filePath = fileName; fileName = NIL; } else { filePath = String(Directory::GetActiveDirectory()).Append(kDelimiter).Append(fileName); fileName = NIL; } } if (fileName == NIL) { Int lastBS = filePath.FindLast(kDelimiter); fileName = filePath.Tail(filePath.Length() - lastBS - 1); filePath[lastBS >= 0 ? lastBS : 0] = 0; } /* Replace ./ elements. */ if (!filePath.EndsWith(kDelimiter)) filePath.Append(kDelimiter); if (filePath.Contains(kDotElement)) filePath.Replace(kDotElement, kDelimiter); if (filePath.StartsWith(String(kDot).Append(kDelimiter))) filePath = String(Directory::GetActiveDirectory()).Append(filePath.Tail(filePath.Length() - 2)); /* Replace ../ elements. */ while (filePath.Contains(kDotsElement)) { Int upPos = filePath.Find(kDotsElement); Int prePos = filePath.Head(upPos).FindLast(kDelimiter); filePath.Replace(filePath.SubString(prePos, upPos - prePos + 3), String()); } if (filePath.EndsWith(kDelimiter)) filePath[filePath.Length() - 1] = 0; } S::File::File(const File &iFile) { fileName = iFile.fileName; filePath = iFile.filePath; } S::File::~File() { } S::File::operator S::String() const { return String(filePath).Append(kDelimiter).Append(fileName); } const S::String &S::File::GetFileName() const { return fileName; } const S::String &S::File::GetFilePath() const { return filePath; } S::Int64 S::File::GetFileSize() const { if (!Exists()) return -1; #ifdef __WIN32__ HANDLE handle = CreateFile(Directory::MakeExtendedPath(*this), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NIL); DWORD sizeLow = 0; DWORD sizeHigh = 0; sizeLow = ::GetFileSize(handle, &sizeHigh); CloseHandle(handle); return (Int64(sizeHigh) << 32) + sizeLow; #else struct stat info; if (stat(String(*this).ConvertTo("UTF-8"), &info) != 0) return 0; return info.st_size; #endif } S::DateTime S::File::GetCreationTime() const { FileTime fileTime; if (!GetFileTime(*this, &fileTime, NIL, NIL)) return DateTime(); return FileTimeToDateTime(fileTime); } S::DateTime S::File::GetAccessTime() const { FileTime fileTime; if (!GetFileTime(*this, NIL, &fileTime, NIL)) return DateTime(); return FileTimeToDateTime(fileTime); } S::DateTime S::File::GetWriteTime() const { FileTime fileTime; if (!GetFileTime(*this, NIL, NIL, &fileTime)) return DateTime(); return FileTimeToDateTime(fileTime); } S::Bool S::File::SetAccessTime(const DateTime &dateTime) { FileTime fileTime = DateTimeToFileTime(dateTime); return SetFileTime(*this, NIL, &fileTime, NIL); } S::Bool S::File::SetWriteTime(const DateTime &dateTime) { FileTime fileTime = DateTimeToFileTime(dateTime); return SetFileTime(*this, NIL, NIL, &fileTime); } S::Bool S::File::Exists() const { #ifdef __WIN32__ WIN32_FIND_DATA findData; HANDLE handle = FindFirstFile(Directory::MakeExtendedPath(*this), &findData); if (handle == INVALID_HANDLE_VALUE) return False; FindClose(handle); if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) return False; #else struct stat info; if (stat(String(*this).ConvertTo("UTF-8"), &info) != 0) return False; if (!S_ISREG(info.st_mode)) return False; #endif return True; } S::Int S::File::Create() { if (Exists()) return Error(); #ifdef __WIN32__ HANDLE handle = CreateFile(Directory::MakeExtendedPath(*this), GENERIC_READ, FILE_SHARE_READ, NIL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NIL); if (handle == INVALID_HANDLE_VALUE) return Error(); CloseHandle(handle); #endif return Success(); } S::Int S::File::Copy(const File &destination) { if (!Exists()) return Error(); #ifdef __WIN32__ Bool result = CopyFile(Directory::MakeExtendedPath(*this), Directory::MakeExtendedPath(destination), True); #else Bool result = False; FILE *source = fopen(String(*this).ConvertTo("UTF-8"), "rb"); FILE *dest = fopen(String(destination).ConvertTo("UTF-8"), "wb"); if (source != NIL && dest != NIL) { Int bytesLeft = GetFileSize(); Int chunkSize = 32768; UnsignedByte *buffer = new UnsignedByte [chunkSize]; while (bytesLeft) { chunkSize = Math::Min(chunkSize, bytesLeft); if (fread(buffer, chunkSize, 1, source) == 1) fwrite(buffer, chunkSize, 1, dest); else break; bytesLeft -= chunkSize; } delete [] buffer; if (!bytesLeft) result = True; } if (source != NIL) fclose(source); if (dest != NIL) fclose(dest); #endif if (result == False) return Error(); else return Success(); } S::Int S::File::Move(const File &destination) { if (!Exists()) return Error(); #ifdef __WIN32__ String fileName = Directory::MakeExtendedPath(*this); UnsignedInt fileAttributes = GetFileAttributes(fileName); SetFileAttributes(fileName, fileAttributes & ~FILE_ATTRIBUTE_READONLY); Bool result = MoveFile(fileName, Directory::MakeExtendedPath(destination)); SetFileAttributes(fileName, fileAttributes); #else Bool result = (rename(String(*this).ConvertTo("UTF-8"), String(destination).ConvertTo("UTF-8")) == 0); #endif if (result == False) return Error(); else return Success(); } S::Int S::File::Delete() { if (!Exists()) return Error(); #ifdef __WIN32__ String fileName = Directory::MakeExtendedPath(*this); SetFileAttributes(fileName, GetFileAttributes(fileName) & ~FILE_ATTRIBUTE_READONLY); Bool result = DeleteFile(fileName); #else Bool result = (remove(String(*this).ConvertTo("UTF-8")) == 0); #endif if (result == False) return Error(); else return Success(); } S::Int S::File::Truncate() { if (!Exists()) return Error(); if (Delete() == Error()) return Error(); return Create(); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/000077500000000000000000000000001516402577000212155ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/Makefile000066400000000000000000000012351516402577000226560ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. # Enter object files here: OBJECTS = bitmap.o color.o font.o surface.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,backends) ALLCMD2 = $(call makein,forms) ALLCMD3 = $(call makein,imageloader) ALLCMD4 = $(call makein,modifiers) CLEANCMD1 = $(call cleanin,backends) CLEANCMD2 = $(call cleanin,forms) CLEANCMD3 = $(call cleanin,imageloader) CLEANCMD4 = $(call cleanin,modifiers) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/000077500000000000000000000000001516402577000227675ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/Makefile000066400000000000000000000013411516402577000244260ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = bitmapbackend.o fontbackend.o surfacebackend.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,cairo) && $(call makein,cocoa) ALLCMD2 = $(call makein,gdi) && $(call makein,gdiplus) ALLCMD3 = $(call makein,haiku) && $(call makein,xlib) CLEANCMD1 = $(call cleanin,cairo) && $(call cleanin,cocoa) CLEANCMD2 = $(call cleanin,gdi) && $(call cleanin,gdiplus) CLEANCMD3 = $(call cleanin,haiku) && $(call cleanin,xlib) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/bitmapbackend.cpp000077500000000000000000000213711516402577000262660ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::GUI::BitmapBackend *CreateBitmapBackend_pV(S::Void *iBitmap) { return new S::GUI::BitmapBackend(iBitmap); } S::GUI::BitmapBackend *CreateBitmapBackend_crSI(const S::GUI::Size &iSize, S::Int iDepth) { return new S::GUI::BitmapBackend(iSize, iDepth); } S::GUI::BitmapBackend *CreateBitmapBackend_cI(const int nil) { return new S::GUI::BitmapBackend(nil); } S::GUI::BitmapBackend *CreateBitmapBackend_crB(const S::GUI::BitmapBackend &iBitmap) { return new S::GUI::BitmapBackend(iBitmap); } S::GUI::BitmapBackend *(*S::GUI::BitmapBackend::backend_creator_pV)(S::Void *) = &CreateBitmapBackend_pV; S::GUI::BitmapBackend *(*S::GUI::BitmapBackend::backend_creator_crSI)(const S::GUI::Size &, S::Int) = &CreateBitmapBackend_crSI; S::GUI::BitmapBackend *(*S::GUI::BitmapBackend::backend_creator_cI)(const int) = &CreateBitmapBackend_cI; S::GUI::BitmapBackend *(*S::GUI::BitmapBackend::backend_creator_crB)(const S::GUI::BitmapBackend &) = &CreateBitmapBackend_crB; S::Int S::GUI::BitmapBackend::SetBackend(BitmapBackend *(*backend)(Void *)) { if (backend == NIL) return Error(); backend_creator_pV = backend; return Success(); } S::Int S::GUI::BitmapBackend::SetBackend(BitmapBackend *(*backend)(const Size &, Int)) { if (backend == NIL) return Error(); backend_creator_crSI = backend; return Success(); } S::Int S::GUI::BitmapBackend::SetBackend(BitmapBackend *(*backend)(const int)) { if (backend == NIL) return Error(); backend_creator_cI = backend; return Success(); } S::Int S::GUI::BitmapBackend::SetBackend(BitmapBackend *(*backend)(const BitmapBackend &)) { if (backend == NIL) return Error(); backend_creator_crB = backend; return Success(); } S::GUI::BitmapBackend *S::GUI::BitmapBackend::CreateBackendInstance(Void *iBitmap) { return backend_creator_pV(iBitmap); } S::GUI::BitmapBackend *S::GUI::BitmapBackend::CreateBackendInstance(const Size &iSize, Int iDepth) { return backend_creator_crSI(iSize, iDepth); } S::GUI::BitmapBackend *S::GUI::BitmapBackend::CreateBackendInstance(const int nil) { return backend_creator_cI(nil); } S::GUI::BitmapBackend *S::GUI::BitmapBackend::CreateBackendInstance(const BitmapBackend &iBitmap) { return backend_creator_crB(iBitmap); } S::GUI::BitmapBackend::BitmapBackend(Void *iBitmap) { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) BitmapGDI(); #endif type = BITMAP_NONE; size = Size(0, 0); depth = 0; bytes = NIL; bpp = 0; align = 0; } S::GUI::BitmapBackend::BitmapBackend(const Size &iSize, Int iDepth) { type = BITMAP_NONE; size = iSize; depth = iDepth; bytes = NIL; bpp = 0; align = 0; } S::GUI::BitmapBackend::BitmapBackend(const int nil) { type = BITMAP_NONE; size = Size(0, 0); depth = 0; bytes = NIL; bpp = 0; align = 0; } S::GUI::BitmapBackend::BitmapBackend(const BitmapBackend &iBitmap) { type = BITMAP_NONE; size = Size(0, 0); depth = 0; bytes = NIL; bpp = 0; align = 0; } S::GUI::BitmapBackend::~BitmapBackend() { } S::Short S::GUI::BitmapBackend::GetBitmapType() const { return type; } const S::GUI::Size &S::GUI::BitmapBackend::GetSize() const { return size; } S::Byte S::GUI::BitmapBackend::GetDepth() const { return depth; } S::UnsignedByte *S::GUI::BitmapBackend::GetBytes() const { return (UnsignedByte *) bytes; } S::Byte S::GUI::BitmapBackend::GetBitsPerPixel() const { return bpp; } S::Byte S::GUI::BitmapBackend::GetLineAlignment() const { return align; } S::Bool S::GUI::BitmapBackend::CreateBitmap(const Size &nSize, Int nDepth) { return False; } S::Bool S::GUI::BitmapBackend::DeleteBitmap() { return True; } S::Bool S::GUI::BitmapBackend::SetSystemBitmap(Void *nBitmap) { return False; } S::Void *S::GUI::BitmapBackend::GetSystemBitmap() const { return NIL; } S::Int S::GUI::BitmapBackend::GrayscaleBitmap() { Point point; for (point.y = 0; point.y < size.cy; point.y++) { for (point.x = 0; point.x < size.cx; point.x++) { Color pixel = GetPixel(point); Int gray = (pixel.GetRed() + pixel.GetGreen() + pixel.GetBlue()) / 3; if (depth == 32) SetPixel(point, Color(gray | (gray << 8) | (gray << 16) | (pixel.GetAlpha() << 24), Color::RGBA)); else SetPixel(point, Color(gray, gray, gray)); } } return Success(); } S::Int S::GUI::BitmapBackend::InvertColors() { Point point; for (point.y = 0; point.y < size.cy; point.y++) { for (point.x = 0; point.x < size.cx; point.x++) { Color pixel = GetPixel(point); Int red = 255 - pixel.GetRed(); Int green = 255 - pixel.GetGreen(); Int blue = 255 - pixel.GetBlue(); if (depth == 32) SetPixel(point, Color(red | (green << 8) | (blue << 16) | (pixel.GetAlpha() << 24), Color::RGBA)); else SetPixel(point, Color(red, green, blue)); } } return Success(); } S::Int S::GUI::BitmapBackend::ReplaceColor(const Color &iColor1, const Color &iColor2) { Color color1 = iColor1.ConvertTo(Color::RGB); Color color2 = iColor2.ConvertTo(Color::RGB); Point point; for (point.y = 0; point.y < size.cy; point.y++) { for (point.x = 0; point.x < size.cx; point.x++) { Color pixel = GetPixel(point); if (pixel.ConvertTo(Color::RGB) != color1) continue; if (depth == 32) SetPixel(point, Color(Long(color2) | (pixel.GetAlpha() << 24), Color::RGBA)); else SetPixel(point, color2); } } return Success(); } S::Int S::GUI::BitmapBackend::SetBackgroundColor(const Color &iColor) { if (depth != 32) return Success(); Color color = iColor.ConvertTo(Color::RGB); Point point; for (point.y = 0; point.y < size.cy; point.y++) { for (point.x = 0; point.x < size.cx; point.x++) { Color pixel = GetPixel(point); if (pixel.GetAlpha() != 255) { Color result = Color((pixel.GetRed() * pixel.GetAlpha() + color.GetRed() * (255 - pixel.GetAlpha())) / 255, (pixel.GetGreen() * pixel.GetAlpha() + color.GetGreen() * (255 - pixel.GetAlpha())) / 255, (pixel.GetBlue() * pixel.GetAlpha() + color.GetBlue() * (255 - pixel.GetAlpha())) / 255); SetPixel(point, 255 << 24 | result); } } } return Success(); } S::GUI::Bitmap S::GUI::BitmapBackend::Scale(const Size &newSize) const { Bitmap bitmap(newSize, depth); Point srcPoint; Point destPoint; Float scaleFactorX = Float(size.cx) / Float(newSize.cx); Float scaleFactorY = Float(size.cy) / Float(newSize.cy); for (destPoint.y = 0; destPoint.y < newSize.cy; destPoint.y++) { for (destPoint.x = 0; destPoint.x < newSize.cx; destPoint.x++) { Float red = 0, green = 0, blue = 0, alpha = 0; for (srcPoint.x = Int(Float(destPoint.x) * scaleFactorX); srcPoint.x < Int(Float(destPoint.x + 1) * scaleFactorX + 0.9999); srcPoint.x++) { for (srcPoint.y = Int(Float(destPoint.y) * scaleFactorY); srcPoint.y < Int(Float(destPoint.y + 1) * scaleFactorY + 0.9999); srcPoint.y++) { Int color = GetPixel(srcPoint); Float weightX = (1.0 - Math::Max(0.0, Float(destPoint.x) * scaleFactorX - Float(srcPoint.x)) - Math::Max(0.0, Float(srcPoint.x + 1) - Float(destPoint.x + 1) * scaleFactorX)) / scaleFactorX; Float weightY = (1.0 - Math::Max(0.0, Float(destPoint.y) * scaleFactorY - Float(srcPoint.y)) - Math::Max(0.0, Float(srcPoint.y + 1) - Float(destPoint.y + 1) * scaleFactorY)) / scaleFactorY; red += Float( color & 255) * weightX * weightY; green += Float((color >> 8) & 255) * weightX * weightY; blue += Float((color >> 16) & 255) * weightX * weightY; if (depth == 32) alpha += Float((color >> 24) & 255) * weightX * weightY; } } bitmap.SetPixel(destPoint, Color(Int(red) | (Int(green) << 8) | (Int(blue) << 16) | (Int(alpha) << 24), Color::RGBA)); } } return bitmap; } S::Bool S::GUI::BitmapBackend::SetPixel(const Point &iPoint, const Color &color) { return False; } S::GUI::Color S::GUI::BitmapBackend::GetPixel(const Point &iPoint) const { return 0; } S::GUI::BitmapBackend &S::GUI::BitmapBackend::operator =(const int nil) { SetSystemBitmap(NIL); return *this; } S::GUI::BitmapBackend &S::GUI::BitmapBackend::operator =(const BitmapBackend &newBitmap) { return *this; } S::Bool S::GUI::BitmapBackend::operator ==(const int nil) const { return True; } S::Bool S::GUI::BitmapBackend::operator !=(const int nil) const { return False; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cairo/000077500000000000000000000000001516402577000240645ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cairo/Makefile000066400000000000000000000014621516402577000255270ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags pangocairo) MYCCOPTS += $(shell pkg-config --cflags gdk-3.0) endif endif else ifeq ($(USE_BUNDLED_LIBFRIBIDI),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support -DFRIBIDI_LIB_STATIC endif endif # Enter object files here: OBJECTS = ifeq ($(BUILD_CAIRO),True) OBJECTS += fontcairo.o surfacecairo.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cairo/fontcairo.cpp000077500000000000000000000061751516402577000265700ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include using namespace X11; #include #include #include S::GUI::FontBackend *CreateFontCairo(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor) { return new S::GUI::FontCairo(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor); } S::Int fontCairoTmp = S::GUI::FontBackend::SetBackend(&CreateFontCairo); S::Int addFontCairoInitTmp = S::AddInitFunction(&S::GUI::FontCairo::Initialize); S::Int S::GUI::FontCairo::Initialize() { Font::Default = "Helvetica"; Setup::FontSize = 1.0; String font = Backends::BackendXLib::QueryGSettings("org.gnome.desktop.interface", "font-name"); Float scaleFactor = Backends::BackendXLib::QueryGSettings("org.gnome.desktop.interface", "text-scaling-factor").ToFloat(); if (font != NIL) { Font::Default = font.SubString(1, font.FindLast(" ") - 1); Setup::FontSize = font.SubString(font.FindLast(" ") + 1, font.Length() - font.FindLast(" ") - 2).ToFloat() / Font::DefaultSize; } if (scaleFactor != 0) Setup::FontSize *= scaleFactor; return Success(); } S::GUI::FontCairo::FontCairo(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor) { type = FONT_CAIRO; } S::GUI::FontCairo::~FontCairo() { } S::GUI::Size S::GUI::FontCairo::GetTextSize(const String &iText) const { if (iText == NIL) return Size(); String text = iText; Int textLength = text.Length(); /* Set up Cairo font and calculate text size. */ Float dpi = Surface().GetSurfaceDPI(); cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); cairo_t *context = cairo_create(surface); PangoLayout *layout = pango_cairo_create_layout(context); PangoFontDescription *desc = pango_font_description_from_string(String(fontName) .Append(" ") .Append(fontStyle & Font::Italic ? "Italic " : "") .Append(fontWeight >= Font::Bold ? "Bold " : "") .Append(String::FromInt(Math::Round(fontSize * dpi / 96.0)))); if (textLength > 0) pango_layout_set_text(layout, text.ConvertTo("UTF-8"), -1); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); int x = 0; int y = 0; pango_layout_get_pixel_size(layout, &x, &y); g_object_unref(layout); cairo_destroy(context); cairo_surface_destroy(surface); return Size(x, y - 2); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cairo/surfacecairo.cpp000077500000000000000000000537151516402577000272540ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include using namespace X11; #include #include #include #include #include #include #if (CAIRO_VERSION_MAJOR == 0 ) || \ (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR <= 8 ) || \ (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR == 9 && CAIRO_VERSION_MICRO <= 1) # define CAIRO_OPERATOR_DIFFERENCE CAIRO_OPERATOR_XOR #endif S::GUI::SurfaceBackend *CreateSurfaceCairo(S::Void *iSurface, const S::GUI::Size &maxSize) { return new S::GUI::SurfaceCairo(iSurface, maxSize); } S::Int surfaceCairoTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceCairo); S::Short S::GUI::SurfaceCairo::surfaceDPI = -1; S::GUI::SurfaceCairo::SurfaceCairo(Void *iWindow, const Size &maxSize) { type = SURFACE_CAIRO; window = (X11::Window) iWindow; paintBitmap = NIL; display = Backends::BackendXLib::GetDisplay(); if (display != NIL) visual = XDefaultVisual(display, XDefaultScreen(display)); else visual = NIL; context = NIL; surface = NIL; paintSurfaceCairo = NIL; paintContextCairo = NIL; if (window != NIL) { size = maxSize; if (maxSize == Size()) { size.cx = XDisplayWidth(display, XDefaultScreen(display)) + 2; size.cy = XDisplayHeight(display, XDefaultScreen(display)) + 2; } fontSize.SetFontSize(GetSurfaceDPI()); rightToLeft.SetSurfaceSize(size); XWindowAttributes windowAttributes; XGetWindowAttributes(display, window, &windowAttributes); paintBitmap = XCreatePixmap(display, DefaultRootWindow(display), size.cx, size.cy, windowAttributes.depth); paintSurfaceCairo = cairo_xlib_surface_create(display, paintBitmap, visual, size.cx, size.cy); paintContextCairo = cairo_create(paintSurfaceCairo); paintRects.Add(Rect(Point(0, 0), size)); cairo_set_antialias(paintContextCairo, CAIRO_ANTIALIAS_NONE); allocSize = size; } } S::GUI::SurfaceCairo::~SurfaceCairo() { if (window != NIL) { cairo_destroy(paintContextCairo); cairo_surface_destroy(paintSurfaceCairo); XFreePixmap(display, paintBitmap); } } S::Int S::GUI::SurfaceCairo::SetSize(const Size &nSize) { size = nSize; rightToLeft.SetSurfaceSize(size); if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success(); if (window != NIL && !painting) { cairo_destroy(paintContextCairo); cairo_surface_destroy(paintSurfaceCairo); XFreePixmap(display, paintBitmap); paintRects.RemoveAll(); XWindowAttributes windowAttributes; XGetWindowAttributes(display, window, &windowAttributes); paintBitmap = XCreatePixmap(display, DefaultRootWindow(display), size.cx, size.cy, windowAttributes.depth); paintSurfaceCairo = cairo_xlib_surface_create(display, paintBitmap, visual, size.cx, size.cy); paintContextCairo = cairo_create(paintSurfaceCairo); paintRects.Add(Rect(Point(0, 0), size)); cairo_set_antialias(paintContextCairo, CAIRO_ANTIALIAS_NONE); } allocSize = nSize; return Success(); } const S::GUI::Size &S::GUI::SurfaceCairo::GetSize() const { return size; } S::Int S::GUI::SurfaceCairo::PaintRect(const Rect &pRect) { if (painting) return Error(); if (window != NIL) { GC gc = XCreateGC(display, window, 0, NIL); XCopyArea(display, paintBitmap, window, gc, pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight(), pRect.left, pRect.top); XFreeGC(display, gc); } return Success(); } S::Int S::GUI::SurfaceCairo::StartPaint(const Rect &iPRect) { if (window == NIL) return Success(); Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast()); cairo_save(paintContextCairo); cairo_rectangle(paintContextCairo, pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight()); cairo_clip(paintContextCairo); paintRects.Add(pRect); painting++; return Success(); } S::Int S::GUI::SurfaceCairo::EndPaint() { if (!painting) return Error(); painting--; if (painting == 0) PaintRect(paintRects.GetLast()); paintRects.RemoveNth(paintRects.Length() - 1); cairo_restore(paintContextCairo); return Success(); } S::Void *S::GUI::SurfaceCairo::GetSystemSurface() const { return (Void *) window; } S::Short S::GUI::SurfaceCairo::GetSurfaceDPI() const { if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor()); if (surfaceDPI != -1) return surfaceDPI; Float dpi = 96.0; if (display != NIL) { /* Load gdk_screen_get_monitor_scale_factor dynamically. */ System::DynamicLoader gdk("gdk-3"); gint (*ex_gdk_screen_get_monitor_scale_factor)(GdkScreen *, gint) = (gint (*)(GdkScreen *, gint)) gdk.GetFunctionAddress("gdk_screen_get_monitor_scale_factor"); /* Get GDK scale factor. */ Float scale = 1.0; if (ex_gdk_screen_get_monitor_scale_factor != NIL) scale = ex_gdk_screen_get_monitor_scale_factor(gdk_screen_get_default(), 0); else scale = (Int64) Number::FromIntString(getenv("GDK_SCALE")); /* Alternatively, query the scale factor from the KDE configuration. */ if (scale <= 1.0) scale = Backends::BackendXLib::QueryKDESettings("KScreen", "ScaleFactor").ToFloat(); /* Alternatively, query custom DPI setting via XfConf. */ if (scale <= 1.0) scale = Backends::BackendXLib::QueryXfConf("xsettings", "/Xft/DPI").ToInt() / dpi; /* Update DPI value if a scale factor has been determined. */ if (scale > 0) dpi *= scale; } surfaceDPI = Math::Round(dpi * Setup::FontSize); return surfaceDPI; } S::Void S::GUI::SurfaceCairo::CreateCairoContext() { if (context != NIL || surface != NIL) return; surface = cairo_xlib_surface_create(display, window, visual, size.cx, size.cy); context = cairo_create(surface); cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE); } S::Void S::GUI::SurfaceCairo::DestroyCairoContext() { if (context == NIL || surface == NIL) return; cairo_destroy(context); cairo_surface_destroy(surface); context = NIL; surface = NIL; } S::Int S::GUI::SurfaceCairo::SetPixel(const Point &iPoint, const Color &color) { if (window == NIL) return Success(); Point point = rightToLeft.TranslatePoint(iPoint); if (!painting) { CreateCairoContext(); cairo_set_source_rgb(context, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0); cairo_rectangle(context, point.x, point.y, 1.0, 1.0); cairo_fill(context); DestroyCairoContext(); } cairo_set_source_rgb(paintContextCairo, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0); cairo_rectangle(paintContextCairo, point.x, point.y, 1.0, 1.0); cairo_fill(paintContextCairo); return Success(); } S::Int S::GUI::SurfaceCairo::Line(const Point &iPos1, const Point &iPos2, const Color &color) { if (window == NIL) return Success(); Point pos1 = rightToLeft.TranslatePoint(iPos1); Point pos2 = rightToLeft.TranslatePoint(iPos2); /* Draw non-straight lines manually to work around bugs in XWayland. */ if (pos1.x != pos2.x && pos1.y != pos2.y) { Int steps = Math::Max(Math::Abs(pos2.x - pos1.x), Math::Abs(pos2.y - pos1.y)); Float xAdvance = steps ? Float(pos2.x - pos1.x) / steps : 0; Float yAdvance = steps ? Float(pos2.y - pos1.y) / steps : 0; if (!painting) { CreateCairoContext(); cairo_set_source_rgb(context, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0); for (Int i = 0; i < steps; i++) cairo_rectangle(context, pos1.x + i * xAdvance, pos1.y + i * yAdvance, 1.0, 1.0); cairo_fill(context); DestroyCairoContext(); } cairo_set_source_rgb(paintContextCairo, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0); for (Int i = 0; i < steps; i++) cairo_rectangle(paintContextCairo, pos1.x + i * xAdvance, pos1.y + i * yAdvance, 1.0, 1.0); cairo_fill(paintContextCairo); } else { if (!painting) { CreateCairoContext(); cairo_set_source_rgb(context, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0); cairo_set_line_width(context, 1.0); cairo_move_to(context, pos1.x + 0.01, pos1.y + 0.01); cairo_line_to(context, pos2.x + 0.01, pos2.y + 0.01); cairo_stroke(context); DestroyCairoContext(); } cairo_set_source_rgb(paintContextCairo, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0); cairo_set_line_width(paintContextCairo, 1.0); cairo_move_to(paintContextCairo, pos1.x + 0.01, pos1.y + 0.01); cairo_line_to(paintContextCairo, pos2.x + 0.01, pos2.y + 0.01); cairo_stroke(paintContextCairo); } return Success(); } S::Int S::GUI::SurfaceCairo::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse) { if (window == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect); if (!painting) { CreateCairoContext(); cairo_set_source_rgb(context, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0); } cairo_set_source_rgb(paintContextCairo, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0); if (style & Rect::Filled) { if (style & Rect::Rounded) { if (!painting) { cairo_move_to(context, rect.left + ellipse.cx, rect.top); cairo_line_to(context, rect.right - ellipse.cx, rect.top); cairo_curve_to(context, rect.right, rect.top, rect.right, rect.top, rect.right, rect.top + ellipse.cy); cairo_line_to(context, rect.right, rect.bottom - ellipse.cy); cairo_curve_to(context, rect.right, rect.bottom, rect.right, rect.bottom, rect.right - ellipse.cx, rect.bottom); cairo_line_to(context, rect.left + ellipse.cx, rect.bottom); cairo_curve_to(context, rect.left, rect.bottom, rect.left, rect.bottom, rect.left, rect.bottom - ellipse.cy); cairo_line_to(context, rect.left, rect.top + ellipse.cy); cairo_curve_to(context, rect.left, rect.top, rect.left, rect.top, rect.left + ellipse.cx, rect.top); cairo_fill(context); } cairo_move_to(paintContextCairo, rect.left + ellipse.cx, rect.top); cairo_line_to(paintContextCairo, rect.right - ellipse.cx, rect.top); cairo_curve_to(paintContextCairo, rect.right, rect.top, rect.right, rect.top, rect.right, rect.top + ellipse.cy); cairo_line_to(paintContextCairo, rect.right, rect.bottom - ellipse.cy); cairo_curve_to(paintContextCairo, rect.right, rect.bottom, rect.right, rect.bottom, rect.right - ellipse.cx, rect.bottom); cairo_line_to(paintContextCairo, rect.left + ellipse.cx, rect.bottom); cairo_curve_to(paintContextCairo, rect.left, rect.bottom, rect.left, rect.bottom, rect.left, rect.bottom - ellipse.cy); cairo_line_to(paintContextCairo, rect.left, rect.top + ellipse.cy); cairo_curve_to(paintContextCairo, rect.left, rect.top, rect.left, rect.top, rect.left + ellipse.cx, rect.top); cairo_fill(paintContextCairo); } else { if (!painting) { cairo_rectangle(context, rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); cairo_fill(context); } cairo_rectangle(paintContextCairo, rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); cairo_fill(paintContextCairo); } } else if (style == Rect::Outlined) { if (!painting) { cairo_set_line_width(context, 1.0); cairo_rectangle(context, rect.left + 0.5, rect.top + 0.5, rect.GetWidth() - 1, rect.GetHeight() - 1); cairo_stroke(context); } cairo_set_line_width(paintContextCairo, 1.0); cairo_rectangle(paintContextCairo, rect.left + 0.5, rect.top + 0.5, rect.GetWidth() - 1, rect.GetHeight() - 1); cairo_stroke(paintContextCairo); } else if (style & Rect::Inverted) { if (cairo_version() >= CAIRO_VERSION_ENCODE(1,9,2)) { if (!painting) { cairo_set_operator(context, CAIRO_OPERATOR_DIFFERENCE); cairo_set_source_rgb(context, 1.0, 1.0, 1.0); cairo_rectangle(context, rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); cairo_fill(context); cairo_set_operator(context, CAIRO_OPERATOR_OVER); } cairo_set_operator(paintContextCairo, CAIRO_OPERATOR_DIFFERENCE); cairo_set_source_rgb(paintContextCairo, 1.0, 1.0, 1.0); cairo_rectangle(paintContextCairo, rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); cairo_fill(paintContextCairo); cairo_set_operator(paintContextCairo, CAIRO_OPERATOR_OVER); } else { Bitmap area(rect.GetSize()); BlitToBitmap(iRect, area, Rect(Point(0, 0), area.GetSize())); area.InvertColors(); BlitFromBitmap(area, Rect(Point(0, 0), area.GetSize()), iRect); } } else if (style & Rect::Dotted) { if (!painting) { for (Int x = rect.left + 1; x < rect.right; x += 2) cairo_rectangle(context, x, rect.top, 1.0, 1.0); for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) cairo_rectangle(context, rect.right - 1, y, 1.0, 1.0); for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) cairo_rectangle(context, x, rect.bottom - 1, 1.0, 1.0); for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) cairo_rectangle(context, rect.left, y, 1.0, 1.0); cairo_fill(context); } for (Int x = rect.left + 1; x < rect.right; x += 2) cairo_rectangle(paintContextCairo, x, rect.top, 1.0, 1.0); for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) cairo_rectangle(paintContextCairo, rect.right - 1, y, 1.0, 1.0); for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) cairo_rectangle(paintContextCairo, x, rect.bottom - 1, 1.0, 1.0); for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) cairo_rectangle(paintContextCairo, rect.left, y, 1.0, 1.0); cairo_fill(paintContextCairo); } if (!painting) DestroyCairoContext(); return Success(); } S::Int S::GUI::SurfaceCairo::SetText(const String &string, const Rect &iRect, const Font &iFont, Bool shadow) { if (window == NIL) return Success(); if (string == NIL) return Error(); if (shadow) return SurfaceBackend::SetText(string, iRect, iFont, shadow); Font font = iFont; Rect rect = iRect; Int lineHeight = 0; /* Set up Cairo font. */ Rect tRect = rightToLeft.TranslateRect(rect); PangoLayout *layout = NIL; PangoFontDescription *desc = pango_font_description_from_string(String(font.GetName()) .Append(" ") .Append(font.GetStyle() & Font::Italic ? "Italic " : "") .Append(font.GetWeight() >= Font::Bold ? "Bold " : "") .Append(String::FromInt(Math::Round(font.GetSize() * fontSize.TranslateY(96) / 96.0)))); if (!painting) { CreateCairoContext(); cairo_save(context); cairo_rectangle(context, tRect.left, tRect.top, tRect.GetWidth(), tRect.GetHeight() + 1); cairo_clip(context); cairo_set_source_rgb(context, font.GetColor().GetRed() / 255.0, font.GetColor().GetGreen() / 255.0, font.GetColor().GetBlue() / 255.0); layout = pango_cairo_create_layout(context); pango_layout_set_font_description(layout, desc); } cairo_save(paintContextCairo); cairo_rectangle(paintContextCairo, tRect.left, tRect.top, tRect.GetWidth(), tRect.GetHeight() + 1); cairo_clip(paintContextCairo); cairo_set_source_rgb(paintContextCairo, font.GetColor().GetRed() / 255.0, font.GetColor().GetGreen() / 255.0, font.GetColor().GetBlue() / 255.0); PangoLayout *paintLayout = pango_cairo_create_layout(paintContextCairo); pango_layout_set_font_description(paintLayout, desc); pango_font_description_free(desc); /* Draw text line by line. */ const Array &lines = string.Explode("\n"); if (lines.Length() > 1) lineHeight = font.GetScaledTextSizeY() + 3; foreach (const String &line, lines) { Int lineLength = line.Length(); if (lineLength == 0) { rect.top += lineHeight; continue; } Rect tRect = rightToLeft.TranslateRect(rect); tRect.left = rightToLeft.GetRightToLeft() ? tRect.right - font.GetScaledTextSizeX(line) : tRect.left; Int utf8Length = (line != NIL ? strlen(line.ConvertTo("UTF-8")) : 0); PangoAttrList *attributes = pango_attr_list_new(); PangoAttribute *underline = pango_attr_underline_new(font.GetStyle() & Font::Underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE); PangoAttribute *strikethrough = pango_attr_strikethrough_new(font.GetStyle() & Font::StrikeOut ? True : False); underline->end_index = utf8Length; strikethrough->end_index = utf8Length; pango_attr_list_insert(attributes, underline); pango_attr_list_insert(attributes, strikethrough); if (!painting) { pango_layout_set_attributes(layout, attributes); pango_layout_set_text(layout, String(line).Append(" ").ConvertTo("UTF-8"), -1); cairo_move_to(context, tRect.left, tRect.top); pango_cairo_show_layout(context, layout); } pango_layout_set_attributes(paintLayout, attributes); pango_layout_set_text(paintLayout, String(line).Append(" ").ConvertTo("UTF-8"), -1); cairo_move_to(paintContextCairo, tRect.left, tRect.top); pango_cairo_show_layout(paintContextCairo, paintLayout); pango_attr_list_unref(attributes); rect.top += lineHeight; } if (!painting) { g_object_unref(layout); cairo_restore(context); DestroyCairoContext(); } g_object_unref(paintLayout); cairo_restore(paintContextCairo); return Success(); } S::Int S::GUI::SurfaceCairo::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style) { if (window == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect); /* Setup colors. */ Color c1 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color2 : color1; Color c2 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color1 : color2; /* Setup Cairo objects and draw gradient. */ cairo_pattern_t *pattern = cairo_pattern_create_linear(0, 0, style == OR_HORZ ? rect.GetWidth() : 0, style == OR_VERT ? rect.GetHeight() : 0); cairo_pattern_add_color_stop_rgb(pattern, 0, c1.GetRed() / 255.0, c1.GetGreen() / 255.0, c1.GetBlue() / 255.0); cairo_pattern_add_color_stop_rgb(pattern, 1, c2.GetRed() / 255.0, c2.GetGreen() / 255.0, c2.GetBlue() / 255.0); if (!painting) { CreateCairoContext(); cairo_set_source(context, pattern); cairo_rectangle(context, rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); cairo_fill(context); DestroyCairoContext(); } cairo_set_source(paintContextCairo, pattern); cairo_rectangle(paintContextCairo, rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); cairo_fill(paintContextCairo); cairo_pattern_destroy(pattern); return Success(); } S::Int S::GUI::SurfaceCairo::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect destRect = rightToLeft.TranslateRect(iDestRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ Bitmap premultipliedBitmap = bitmap; PremultiplyAlpha(premultipliedBitmap); Size srcSize = premultipliedBitmap.GetSize(); cairo_format_t srcFormat = premultipliedBitmap.GetDepth() == 32 ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24; cairo_surface_t *srcSurface = cairo_image_surface_create_for_data(premultipliedBitmap.GetBytes(), srcFormat, srcSize.cx, srcSize.cy, srcSize.cx * 4); if (!painting) { CreateCairoContext(); cairo_rectangle(context, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()); cairo_clip(context); cairo_translate(context, destRect.left, destRect.top); cairo_scale(context, (float) destRect.GetWidth() / srcRect.GetWidth(), (float) destRect.GetHeight() / srcRect.GetHeight()); cairo_set_source_surface(context, srcSurface, -srcRect.left, -srcRect.top); cairo_paint(context); DestroyCairoContext(); } cairo_save(paintContextCairo); cairo_rectangle(paintContextCairo, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()); cairo_clip(paintContextCairo); cairo_translate(paintContextCairo, destRect.left, destRect.top); cairo_scale(paintContextCairo, (float) destRect.GetWidth() / srcRect.GetWidth(), (float) destRect.GetHeight() / srcRect.GetHeight()); cairo_set_source_surface(paintContextCairo, srcSurface, -srcRect.left, -srcRect.top); cairo_paint(paintContextCairo); cairo_restore(paintContextCairo); cairo_surface_destroy(srcSurface); return Success(); } S::Int S::GUI::SurfaceCairo::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect srcRect = rightToLeft.TranslateRect(iSrcRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ cairo_surface_t *bitmapSurface = cairo_image_surface_create_for_data(bitmap.GetBytes(), CAIRO_FORMAT_RGB24, bitmap.GetSize().cx, bitmap.GetSize().cy, bitmap.GetSize().cx * 4); cairo_t *bitmapContext = cairo_create(bitmapSurface); cairo_rectangle(bitmapContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()); cairo_clip(bitmapContext); cairo_translate(bitmapContext, destRect.left, destRect.top); cairo_scale(bitmapContext, (float) destRect.GetWidth() / srcRect.GetWidth(), (float) destRect.GetHeight() / srcRect.GetHeight()); cairo_set_source_surface(bitmapContext, surface, -srcRect.left, -srcRect.top); cairo_paint(bitmapContext); cairo_destroy(bitmapContext); cairo_surface_destroy(bitmapSurface); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/000077500000000000000000000000001516402577000240535ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/Makefile000066400000000000000000000007041516402577000255140ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_OSX),True) OBJECTS += bitmapcocoa.o fontcocoa.o surfacecocoa.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/bitmapcocoa.mm000066400000000000000000000144631516402577000266770ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::GUI::BitmapBackend *CreateBitmapCocoa_pV(S::Void *iBitmap) { return new S::GUI::BitmapCocoa(iBitmap); } S::GUI::BitmapBackend *CreateBitmapCocoa_crSI(const S::GUI::Size &iSize, S::Int iDepth) { return new S::GUI::BitmapCocoa(iSize, iDepth); } S::GUI::BitmapBackend *CreateBitmapCocoa_cI(const int null) { return new S::GUI::BitmapCocoa(null); } S::GUI::BitmapBackend *CreateBitmapCocoa_crB(const S::GUI::BitmapBackend &iBitmap) { return new S::GUI::BitmapCocoa((const S::GUI::BitmapCocoa &) iBitmap); } S::Int bitmapCocoaTmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapCocoa_pV); S::Int bitmapCocoaTmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapCocoa_crSI); S::Int bitmapCocoaTmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapCocoa_cI); S::Int bitmapCocoaTmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapCocoa_crB); S::GUI::BitmapCocoa::BitmapCocoa(Void *iBitmap) { Initialize(); SetSystemBitmap(iBitmap); } S::GUI::BitmapCocoa::BitmapCocoa(const Size &iSize, Int iDepth) { Initialize(); CreateBitmap(iSize, iDepth); } S::GUI::BitmapCocoa::BitmapCocoa(const int null) { Initialize(); SetSystemBitmap(NIL); } S::GUI::BitmapCocoa::BitmapCocoa(const BitmapCocoa &iBitmap) { Initialize(); SetSystemBitmap((Void *) iBitmap.bitmap); depth = iBitmap.depth; } S::GUI::BitmapCocoa::~BitmapCocoa() { DeleteBitmap(); } S::Void S::GUI::BitmapCocoa::Initialize() { type = BITMAP_COCOA; bitmap = nil; image = nil; } S::Bool S::GUI::BitmapCocoa::CreateBitmap(const Size &nSize, Int nDepth) { DeleteBitmap(); if (nDepth == -1) nDepth = [[NSScreen deepestScreen] depth]; if (nDepth != 24 && nDepth != 32) nDepth = 24; bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: nil pixelsWide: nSize.cx pixelsHigh: nSize.cy bitsPerSample: 8 samplesPerPixel: nDepth == 32 ? 4 : 3 hasAlpha: nDepth == 32 isPlanar: NO colorSpaceName: NSCalibratedRGBColorSpace bitmapFormat: 0 bytesPerRow: 4 * nSize.cx bitsPerPixel: 32]; if (bitmap == nil) return False; bytes = [bitmap bitmapData]; size = nSize; depth = nDepth; bpp = 32; align = 4; return True; } S::Bool S::GUI::BitmapCocoa::DeleteBitmap() { if (bitmap != nil) { if (image != nil) { [image release]; image = nil; } [bitmap release]; bitmap = nil; size = Size(0, 0); depth = 0; bytes = NIL; bpp = 0; align = 0; } return True; } S::GUI::Bitmap S::GUI::BitmapCocoa::Scale(const Size &newSize) const { Bitmap result(newSize, depth); NSImage *image = (NSImage *) result.GetSystemBitmap(); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep: (NSBitmapImageRep *) [[image representations] objectAtIndex: 0]]; [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext: context]; [bitmap drawInRect: NSMakeRect(0, 0, newSize.cx, newSize.cy)]; [image recache]; [NSGraphicsContext restoreGraphicsState]; [pool release]; return result; } S::Bool S::GUI::BitmapCocoa::SetSystemBitmap(Void *nBitmap) { if (nBitmap == GetSystemBitmap()) return True; if (nBitmap == NIL) { DeleteBitmap(); } else { CreateBitmap(Size([(NSBitmapImageRep *) nBitmap pixelsWide], [(NSBitmapImageRep *) nBitmap pixelsHigh]), 8 * [(NSBitmapImageRep *) nBitmap samplesPerPixel]); /* Copy source bitmap to destination. */ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep: bitmap]; [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext: context]; [(NSBitmapImageRep *) nBitmap drawInRect: NSMakeRect(0, 0, size.cx, size.cy)]; [NSGraphicsContext restoreGraphicsState]; [pool release]; } return True; } S::Void *S::GUI::BitmapCocoa::GetSystemBitmap() const { if (image == nil && bitmap != nil) { image = [[NSImage alloc] initWithSize: NSMakeSize(size.cx, size.cy)]; [image addRepresentation: bitmap]; [image setFlipped: YES]; } return (Void *) image; } S::Bool S::GUI::BitmapCocoa::SetPixel(const Point &point, const Color &iColor) { if (bytes == NIL) return False; if (point.y >= size.cy || point.x >= size.cx) return False; Color color = iColor.ConvertTo(Color::RGBA); UnsignedByte *data = ((UnsignedByte *) bytes); Int offset = point.y * (size.cx * 4) + point.x * 4; switch (depth) { case 24: data[offset + 2] = (color >> 16) & 255; data[offset + 1] = (color >> 8) & 255; data[offset + 0] = color & 255; return True; case 32: data[offset + 2] = (color >> 16) & 255; data[offset + 1] = (color >> 8) & 255; data[offset + 0] = color & 255; data[offset + 3] = (color >> 24) & 255; return True; } return False; } S::GUI::Color S::GUI::BitmapCocoa::GetPixel(const Point &point) const { if (bytes == NIL) return 0; if (point.y >= size.cy || point.x >= size.cx) return 0; UnsignedByte *data = ((UnsignedByte *) bytes); Int offset = point.y * (size.cx * 4) + point.x * 4; switch (depth) { case 24: return Color( data[offset + 2] << 16 | data[offset + 1] << 8 | data[offset + 0], Color::RGB); case 32: return Color(data[offset + 3] << 24 | data[offset + 2] << 16 | data[offset + 1] << 8 | data[offset + 0], Color::RGBA); } return 0; } S::GUI::BitmapBackend &S::GUI::BitmapCocoa::operator =(const BitmapBackend &newBitmap) { if (&newBitmap == this) return *this; SetSystemBitmap((Void *) ((BitmapCocoa &) newBitmap).bitmap); return *this; } S::Bool S::GUI::BitmapCocoa::operator ==(const int null) const { if (bitmap == NIL) return True; else return False; } S::Bool S::GUI::BitmapCocoa::operator !=(const int null) const { if (bitmap == NIL) return False; else return True; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/fontcocoa.mm000066400000000000000000000073761516402577000263760ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::GUI::FontBackend *CreateFontCocoa(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor) { return new S::GUI::FontCocoa(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor); } S::Int fontCocoaTmp = S::GUI::FontBackend::SetBackend(&CreateFontCocoa); S::Int addFontCocoaInitTmp = S::AddInitFunction(&S::GUI::FontCocoa::Initialize); S::Int S::GUI::FontCocoa::Initialize() { /* The default font size on macOS is 13pt. However, apps like Finder and other Apple * software use various font sizes between 11 and 13pt depending on the kind of label. * * smooth apps look too bulky with the default 13pt font size, so we apply a scale * factor to reduce the standard size to 12pt. */ Float fontSize = [NSFont systemFontSize] / 13.0 * 12.0; Font::Default.ImportFrom("UTF-8", [[[NSFont systemFontOfSize: fontSize] familyName] UTF8String]); Setup::FontSize = fontSize / 96.0 * 72.0 / Font::DefaultSize; return Success(); } S::GUI::FontCocoa::FontCocoa(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor) { type = FONT_COCOA; } S::GUI::FontCocoa::~FontCocoa() { } S::GUI::Size S::GUI::FontCocoa::GetTextSize(const String &text) const { if (text == NIL) return Size(); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSFont *font = GetNativeFont(Font(fontName, fontSize, fontWeight, fontStyle)); NSDictionary *attributes = [NSDictionary dictionaryWithObject: font forKey: NSFontAttributeName]; NSAttributedString *string = [[[NSAttributedString alloc] initWithString: [NSString stringWithUTF8String: text.ConvertTo("UTF-8")] attributes: attributes] autorelease]; NSSize size = [string size]; [pool release]; return Size(size.width, size.height - 2); } NSFont *S::GUI::FontCocoa::GetNativeFont(const Font &font) { static SEL monoSpacedDigitSystemFontSelector = @selector(monospacedDigitSystemFontOfSize:weight:); static Bool queryMonospacedDigitFont = [[NSFont class] respondsToSelector: monoSpacedDigitSystemFontSelector]; /* Get font object. */ Float dpi = Surface().GetSurfaceDPI(); NSFont *nativeFont = nil; if (queryMonospacedDigitFont && font.GetName() == Font::Default) { /* Get font with monospaced digits if available. */ nativeFont = ((NSFont *(*)(id, SEL, CGFloat, CGFloat)) [[NSFont class] methodForSelector: monoSpacedDigitSystemFontSelector])([NSFont class], monoSpacedDigitSystemFontSelector, font.GetSize() * dpi / 72.0, 0.0); } else { /* Otherwise use standard system font. */ nativeFont = [[NSFontManager sharedFontManager] fontWithFamily: [NSString stringWithUTF8String: font.GetName().ConvertTo("UTF-8")] traits: 0 weight: 5 size: font.GetSize() * dpi / 72.0]; } /* Set font traits. */ if (font.GetWeight() >= Font::Bold) nativeFont = [[NSFontManager sharedFontManager] convertFont: nativeFont toHaveTrait: NSBoldFontMask]; if (font.GetStyle() & Font::Italic) nativeFont = [[NSFontManager sharedFontManager] convertFont: nativeFont toHaveTrait: NSItalicFontMask]; return nativeFont; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/surfacecocoa.mm000066400000000000000000000372011516402577000270460ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2023 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include S::GUI::SurfaceBackend *CreateSurfaceCocoa(S::Void *iSurface, const S::GUI::Size &maxSize) { return new S::GUI::SurfaceCocoa(iSurface, maxSize); } S::Int surfaceCocoaTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceCocoa); namespace smooth { namespace GUI { static NSColor *NSColorForColor(const Color &color) { return [NSColor colorWithCalibratedRed: color.GetRed() / 255.0 green: color.GetGreen() / 255.0 blue: color.GetBlue() / 255.0 alpha: 1.0]; } } } S::Short S::GUI::SurfaceCocoa::surfaceDPI = -1; S::GUI::SurfaceCocoa::SurfaceCocoa(Void *iWindow, const Size &maxSize) { type = SURFACE_COCOA; window = (NSWindow *) iWindow; paintImage = nil; paintBitmap = nil; paintPending = False; lockCount = 0; if (window != NIL) { size = maxSize; if (maxSize == Size()) { NSScreen *screen = [NSScreen mainScreen]; NSRect frame = [screen visibleFrame]; size.cx = frame.size.width; size.cy = frame.size.height; } fontSize.SetFontSize(GetSurfaceDPI()); rightToLeft.SetSurfaceSize(size); paintImage = [[NSImage alloc] initWithSize: NSMakeSize(size.cx, size.cy)]; paintBitmap = [[[window contentView] bitmapImageRepForCachingDisplayInRect: NSMakeRect(0, 0, size.cx, size.cy)] retain]; [paintImage addRepresentation: paintBitmap]; paintRects.Add(Rect(Point(0, 0), size)); [NSBezierPath setDefaultLineWidth: 0.0]; allocSize = size; } } S::GUI::SurfaceCocoa::~SurfaceCocoa() { if (window != NIL) { [paintBitmap release]; [paintImage release]; } } S::Int S::GUI::SurfaceCocoa::Lock() { SurfaceBackend::Lock(); if (++lockCount > 1 || window == NIL) return Success(); /* Draw pending areas when this is the main thread. */ if (paintPending && [NSThread isMainThread]) PaintRect(paintPendingRect); /* Otherwise spin while waiting for painting to occur. */ while (paintPending) { lockCount--; SurfaceBackend::Release(); Application::Lock::ResumeLock(Application::Lock::SuspendLock()); SurfaceBackend::Lock(); lockCount++; } /* Create autorelease pool. */ pool = [[NSAutoreleasePool alloc] init]; return Success(); } S::Int S::GUI::SurfaceCocoa::Release() { if (--lockCount == 0 && window != NIL) [pool release]; SurfaceBackend::Release(); return Success(); } S::Int S::GUI::SurfaceCocoa::SetSize(const Size &nSize) { size = nSize; rightToLeft.SetSurfaceSize(size); if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success(); if (window != NIL && !painting) { paintRects.RemoveAll(); [paintBitmap release]; [paintImage release]; paintImage = [[NSImage alloc] initWithSize: NSMakeSize(size.cx, size.cy)]; paintBitmap = [[[window contentView] bitmapImageRepForCachingDisplayInRect: NSMakeRect(0, 0, size.cx, size.cy)] retain]; [paintImage addRepresentation: paintBitmap]; paintRects.Add(Rect(Point(0, 0), size)); } allocSize = nSize; return Success(); } const S::GUI::Size &S::GUI::SurfaceCocoa::GetSize() const { return size; } S::Int S::GUI::SurfaceCocoa::PaintRect(const Rect &pRect) { if (painting) return Error(); if (window == NIL || ![window isVisible]) return Success(); NSView *contentView = [window contentView]; NSRect rect = NSMakeRect(pRect.left, pRect.top, pRect.right - pRect.left, pRect.bottom - pRect.top); if ([NSThread isMainThread]) { if ([NSView focusView] == contentView) { /* Draw cached image if focussed. */ [paintImage drawInRect: rect fromRect: rect operation: NSCompositeCopy fraction: 1.0]; } else if (!Backends::BackendCocoa::IsOSXVersionAtLeast(10, 7, 0)) { /* Lock content view and draw on older OS X versions. */ [contentView lockFocus]; [paintImage drawInRect: rect fromRect: rect operation: NSCompositeCopy fraction: 1.0]; [window flushWindow]; [contentView unlockFocus]; } else { /* Otherwise call displayRect: if not focussed. */ [contentView displayRect: rect]; } paintPending = False; } else { /* Call displayRect: on main thread if in another one. */ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [contentView methodSignatureForSelector: @selector(displayRect:)]]; [invocation setTarget: contentView]; [invocation setSelector: @selector(displayRect:)]; [invocation setArgument: &rect atIndex: 2]; [invocation retainArguments]; [invocation performSelectorOnMainThread: @selector(invoke) withObject: nil waitUntilDone: NO]; paintPending = True; paintPendingRect = pRect; } return Success(); } S::Int S::GUI::SurfaceCocoa::StartPaint(const Rect &iPRect) { if (window == NIL) return Success(); Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast()); [NSGraphicsContext saveGraphicsState]; if (painting == 0) [NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithBitmapImageRep: paintBitmap]]; NSRectClip(NSMakeRect(pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight())); paintRects.Add(pRect); painting++; return Success(); } S::Int S::GUI::SurfaceCocoa::EndPaint() { if (!painting) return Error(); painting--; Rect paintRect = paintRects.GetLast(); paintRects.RemoveNth(paintRects.Length() - 1); [NSGraphicsContext restoreGraphicsState]; if (painting == 0) PaintRect(paintRect); return Success(); } S::Void *S::GUI::SurfaceCocoa::GetSystemSurface() const { return (Void *) window; } S::Short S::GUI::SurfaceCocoa::GetSurfaceDPI() const { if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor()); if (surfaceDPI != -1) return surfaceDPI; Float dpi = 96.0; surfaceDPI = Math::Round(dpi * Setup::FontSize); return surfaceDPI; } S::Float S::GUI::SurfaceCocoa::GetScaleFactor() const { /* Get screen information. */ static SEL scaleFactorSelector = @selector(backingScaleFactor); static Bool canQueryScaleFactor = [[NSScreen mainScreen] respondsToSelector: scaleFactorSelector]; if (!canQueryScaleFactor || window == NIL || [window screen] == nil) return 1.0; NSScreen *screen = [window screen]; return ((CGFloat (*)(id, SEL)) [screen methodForSelector: scaleFactorSelector])(screen, scaleFactorSelector); } S::Int S::GUI::SurfaceCocoa::SetPixel(const Point &iPoint, const Color &color) { if (window == NIL) return Success(); Point point = rightToLeft.TranslatePoint(iPoint); Bool endPaint = painting ? False : StartPaint(Rect(point, Size(1, 1))) == Success(); [[NSGraphicsContext currentContext] setShouldAntialias: NO]; [NSColorForColor(color) set]; NSRectFill(NSMakeRect(point.x, point.y, 1, 1)); if (endPaint) EndPaint(); return Success(); } S::Int S::GUI::SurfaceCocoa::Line(const Point &iPos1, const Point &iPos2, const Color &color) { if (window == NIL) return Success(); /* Convert coordinates. */ Point pos1 = rightToLeft.TranslatePoint(iPos1); Point pos2 = rightToLeft.TranslatePoint(iPos2); NSPoint point1 = NSMakePoint(pos1.x + 0.5, pos1.y + 0.5); NSPoint point2 = NSMakePoint(pos2.x + 0.5, pos2.y + 0.5); /* Adjust to Windows GDI behavior for diagonal lines. */ Float scaleFactor = GetScaleFactor(); if (Math::Abs(pos2.x - pos1.x) == Math::Abs(pos2.y - pos1.y) && scaleFactor == 1.0) { if (pos1.x < pos2.x && pos1.y < pos2.y) { point2.x--; point2.y--; } if (pos1.x > pos2.x && pos1.y < pos2.y) { point2.x++; point2.y--; } } /* Adjust to Windows GDI behaviour for horizontal and vertical lines. */ if (point1.x < point2.x) { point1.x -= 0.5; point2.x -= 0.5; } if (point1.x > point2.x) { point1.x += 0.5; point2.x += 0.5; } if (point1.y < point2.y) { point1.y -= 0.5; point2.y -= 0.5; } if (point1.y > point2.y) { point1.y += 0.5; point2.y += 0.5; } Rect rect; rect.left = Math::Min(point1.x, point2.x); rect.top = Math::Min(point1.y, point2.y); rect.right = Math::Max(point1.x, point2.x) + 1; rect.bottom = Math::Max(point1.y, point2.y) + 1; Bool endPaint = painting ? False : StartPaint(rect) == Success(); [[NSGraphicsContext currentContext] setShouldAntialias: NO]; [NSColorForColor(color) set]; NSBezierPath *path = [NSBezierPath bezierPath]; [path setLineWidth: 1.0]; [path moveToPoint: point1]; [path lineToPoint: point2]; [path stroke]; if (endPaint) EndPaint(); return Success(); } S::Int S::GUI::SurfaceCocoa::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse) { if (window == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect); if (style & Rect::Filled) { if (style & Rect::Rounded) { /* ToDo: Implement drawing of rounded boxes. */ } else { Bool endPaint = painting ? False : StartPaint(rect) == Success(); [[NSGraphicsContext currentContext] setShouldAntialias: NO]; [NSColorForColor(color) set]; NSRectFill(NSMakeRect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight())); if (endPaint) EndPaint(); } } else if (style == Rect::Outlined) { Bool endPaint = painting ? False : StartPaint(rect) == Success(); [[NSGraphicsContext currentContext] setShouldAntialias: NO]; [NSColorForColor(color) set]; NSFrameRect(NSMakeRect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight())); if (endPaint) EndPaint(); } else if (style & Rect::Inverted) { Float scaleFactor = GetScaleFactor(); Bitmap area(rect.GetSize() * scaleFactor); BlitToBitmap(iRect, area, Rect(Point(0, 0), area.GetSize())); area.InvertColors(); BlitFromBitmap(area, Rect(Point(0, 0), area.GetSize()), iRect); } else if (style & Rect::Dotted) { Bool endPaint = painting ? False : StartPaint(rect) == Success(); [[NSGraphicsContext currentContext] setShouldAntialias: NO]; [NSColorForColor(color) set]; NSBezierPath *path = [NSBezierPath bezierPathWithRect: NSMakeRect(rect.left + 0.5, rect.top + 0.5, rect.GetWidth() - 1, rect.GetHeight() - 1)]; CGFloat pattern[2] = { 1.0, 1.0 }; [path setLineDash: pattern count: 2 phase: 1]; [path setLineWidth: 1.0]; [path stroke]; if (endPaint) EndPaint(); } return Success(); } S::Int S::GUI::SurfaceCocoa::SetText(const String &string, const Rect &iRect, const Font &font, Bool shadow) { if (window == NIL) return Success(); if (string == NIL) return Error(); if (shadow) return SurfaceBackend::SetText(string, iRect, font, shadow); NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys: FontCocoa::GetNativeFont(font), NSFontAttributeName, NSColorForColor(font.GetColor()), NSForegroundColorAttributeName, nil]; if (font.GetStyle() & Font::Underline) [attributes setObject: [NSNumber numberWithInt: NSUnderlineStyleSingle] forKey: NSUnderlineStyleAttributeName]; if (font.GetStyle() & Font::StrikeOut) [attributes setObject: [NSNumber numberWithInt: NSUnderlineStyleSingle] forKey: NSStrikethroughStyleAttributeName]; Rect rect = iRect; Int lineHeight = font.GetScaledTextSizeY() + 3; const Array &lines = string.Explode("\n"); /* Draw to window. */ Rect tRect = rightToLeft.TranslateRect(rect); NSAffineTransform *transform = [NSAffineTransform transform]; Bool endPaint = painting ? False : StartPaint(rect) == Success(); [[NSGraphicsContext currentContext] setShouldAntialias: YES]; [NSGraphicsContext saveGraphicsState]; NSRectClip(NSMakeRect(tRect.left, tRect.top, tRect.GetWidth(), tRect.GetHeight())); [transform scaleXBy: 1.0 yBy: -1.0]; [transform concat]; foreach (const String &line, lines) { tRect.left = rightToLeft.GetRightToLeft() ? tRect.right - font.GetScaledTextSizeX(line) : tRect.left; tRect.top += lineHeight; if (line != NIL) { NSString *string = [NSString stringWithUTF8String: line.ConvertTo("UTF-8")]; [string drawAtPoint: NSMakePoint(tRect.left, -1.0 * (tRect.top - 1)) withAttributes: attributes]; } } [NSGraphicsContext restoreGraphicsState]; if (endPaint) EndPaint(); [attributes release]; return Success(); } S::Int S::GUI::SurfaceCocoa::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style) { if (window == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect); Bool endPaint = painting ? False : StartPaint(rect) == Success(); [[NSGraphicsContext currentContext] setShouldAntialias: NO]; NSGradient *gradient = [[NSGradient alloc] initWithStartingColor: NSColorForColor(color1) endingColor: NSColorForColor(color2)]; [gradient drawInRect: NSMakeRect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight()) angle: (style == OR_HORZ ? (rightToLeft.GetRightToLeft() ? 180 : 0.0) : 270)]; [gradient release]; if (endPaint) EndPaint(); return Success(); } S::Int S::GUI::SurfaceCocoa::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect destRect = rightToLeft.TranslateRect(iDestRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ Bitmap premultipliedBitmap = bitmap; PremultiplyAlpha(premultipliedBitmap); NSImage *image = (NSImage *) premultipliedBitmap.GetSystemBitmap(); Bool endPaint = painting ? False : StartPaint(destRect) == Success(); [image drawInRect: NSMakeRect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()) fromRect: NSMakeRect(srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight()) operation: NSCompositeSourceOver fraction: 1.0]; if (endPaint) EndPaint(); return Success(); } S::Int S::GUI::SurfaceCocoa::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect srcRect = rightToLeft.TranslateRect(iSrcRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Create context for destination bitmap. */ NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep: (NSBitmapImageRep *) [[(NSImage *) bitmap.GetSystemBitmap() representations] objectAtIndex: 0]]; [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext: context]; /* Transform to adjust for flipped destination context. */ NSAffineTransform *transform = [NSAffineTransform transform]; [transform scaleXBy: 1.0 yBy: -1.0]; [transform translateXBy: 0.0 yBy: -1.0 * destRect.GetHeight()]; [transform set]; /* Copy drawing cache contents to destination context. */ [paintImage drawInRect: NSMakeRect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()) fromRect: NSMakeRect(srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight()) operation: NSCompositeCopy fraction: 1.0]; [(NSImage *) bitmap.GetSystemBitmap() recache]; [NSGraphicsContext restoreGraphicsState]; return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/fontbackend.cpp000077500000000000000000000122411516402577000257540ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif /* Cache computed text extents as this is very slow on Haiku. */ namespace smooth { class ExtentsCacheEntry { private: UnsignedInt32 crc32; GUI::Size extents; public: ExtentsCacheEntry(const String &text, const String &fontName, Int fontSize, Int fontWeight, Int fontStyle) { crc32 = String(text).Append(fontName) .Append(String::FromInt(fontSize << 16 | fontWeight << 4 | fontStyle)).ComputeCRC32(); } UnsignedInt32 GetCRC32() const { return crc32; } const GUI::Size &GetExtents() const { return extents; } Void SetExtents(const GUI::Size &nExtents) { extents = nExtents; } }; static Array extentsCache; }; S::Int addFontBackendInitTmp = S::AddInitFunction(&S::GUI::FontBackend::Initialize); S::Int addFontBackendFreeTmp = S::AddFreeFunction(&S::GUI::FontBackend::Free); S::GUI::FontBackend *CreateFontBackend(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor) { return new S::GUI::FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor); } S::GUI::FontBackend *(*S::GUI::FontBackend::backend_creator)(const String &, Short, Short, Short, const Color &) = &CreateFontBackend; S::Int S::GUI::FontBackend::SetBackend(FontBackend *(*backend)(const String &, Short, Short, Short, const Color &)) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::GUI::FontBackend *S::GUI::FontBackend::CreateBackendInstance(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) { return backend_creator(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor); } S::GUI::FontBackend::FontBackend(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) FontGDI(); #endif type = FONT_NONE; fontName = iFontName; fontSize = iFontSize; fontColor = iFontColor; fontWeight = iFontWeight; fontStyle = iFontStyle; } S::GUI::FontBackend::~FontBackend() { } S::Int S::GUI::FontBackend::Initialize() { extentsCache.EnableLocking(); return Success(); } S::Int S::GUI::FontBackend::Free() { foreach (ExtentsCacheEntry *entry, extentsCache) delete entry; extentsCache.RemoveAll(); return Success(); } S::Short S::GUI::FontBackend::GetFontType() const { return type; } S::Int S::GUI::FontBackend::GetTextSizeX(const String &text, Bool scaled) const { if (text == NIL) return 0; Int length = text.Length(); Int offset = 0; Int sizex = 0; for (Int i = 0; i <= length; i++) { if (i < length && text[i] != '\n') continue; sizex = (Int) Math::Max(sizex, GetTextSize(text.SubString(offset, i - offset), scaled).cx); offset = i + 1; } return sizex; } S::Int S::GUI::FontBackend::GetTextSizeY(const String &text, Bool scaled) const { if (text == NIL) return 0; Int length = text.Length(); Int lines = 1; for (Int i = 0; i < length; i++) { if (text[i] == '\n') lines++; } /* Line height is always the same regardless of the actual text, * so we use a default text here and multiply by the numer of lines. */ static String string = "abcdefghijklmnopqrstuvwxyz"; return (lines * (GetTextSize(string, scaled).cy - 1)) + (lines - 1) * 3; } S::GUI::Size S::GUI::FontBackend::GetTextSize(const String &text, Bool scaled) const { if (text == NIL) return Size(); /* Check for existing cache entry. */ ExtentsCacheEntry entry(text, fontName, fontSize, fontWeight, fontStyle); Float dpi = Surface().GetSurfaceDPI(); Int crc = entry.GetCRC32(); if (ExtentsCacheEntry *cacheEntry = extentsCache.Get(crc)) { if (scaled || Math::Abs(dpi - 96.0) < 0.1) return cacheEntry->GetExtents(); else return cacheEntry->GetExtents() * 96.0 / dpi; } /* Compute scaled text size. */ Size size = GetTextSize(text); entry.SetExtents(size); /* Save at most 2048 cache entries. */ if (extentsCache.Length() >= 2048) { for (Int i = 0; i < 1024; i++) { delete extentsCache.GetFirst(); extentsCache.RemoveNth(0); } } extentsCache.Add(new ExtentsCacheEntry(entry), crc); /* Return computed text size. */ if (scaled || Math::Abs(dpi - 96.0) < 0.1) return size; else return size * 96.0 / dpi; } S::GUI::Size S::GUI::FontBackend::GetTextSize(const String &text) const { return Size(); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/000077500000000000000000000000001516402577000235325ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/Makefile000066400000000000000000000012161516402577000251720ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifeq ($(USE_BUNDLED_LIBFRIBIDI),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support -DFRIBIDI_LIB_STATIC endif # Enter object files here: OBJECTS = ifeq ($(BUILD_WIN32),True) ifneq ($(BUILD_GDIPLUS),True) OBJECTS += bitmapgdi.o fontgdi.o surfacegdi.o endif endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/bitmapgdi.cpp000077500000000000000000000135271516402577000262110ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::GUI::BitmapBackend *CreateBitmapGDI_pV(S::Void *iBitmap) { return new S::GUI::BitmapGDI(iBitmap); } S::GUI::BitmapBackend *CreateBitmapGDI_crSI(const S::GUI::Size &iSize, S::Int iDepth) { return new S::GUI::BitmapGDI(iSize, iDepth); } S::GUI::BitmapBackend *CreateBitmapGDI_cI(const int nil) { return new S::GUI::BitmapGDI(nil); } S::GUI::BitmapBackend *CreateBitmapGDI_crB(const S::GUI::BitmapBackend &iBitmap) { return new S::GUI::BitmapGDI((const S::GUI::BitmapGDI &) iBitmap); } S::Int bitmapGDITmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDI_pV); S::Int bitmapGDITmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDI_crSI); S::Int bitmapGDITmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDI_cI); S::Int bitmapGDITmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDI_crB); S::GUI::BitmapGDI::BitmapGDI(Void *iBitmap) { type = BITMAP_GDI; bitmap = NIL; SetSystemBitmap(iBitmap); } S::GUI::BitmapGDI::BitmapGDI(const Size &iSize, Int iDepth) { type = BITMAP_GDI; bitmap = NIL; CreateBitmap(iSize, iDepth); } S::GUI::BitmapGDI::BitmapGDI(const int nil) { type = BITMAP_GDI; bitmap = NIL; SetSystemBitmap(NIL); } S::GUI::BitmapGDI::BitmapGDI(const BitmapGDI &iBitmap) { type = BITMAP_GDI; bitmap = NIL; SetSystemBitmap(iBitmap.bitmap); } S::GUI::BitmapGDI::~BitmapGDI() { DeleteBitmap(); } S::Bool S::GUI::BitmapGDI::CreateBitmap(const Size &nSize, Int nDepth) { DeleteBitmap(); if (nDepth == -1) nDepth = 24; if (nDepth != 24 && nDepth != 32) nDepth = 24; UnsignedByte *buffer = new UnsignedByte [sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)]; BITMAPINFO *bmpInfo = (BITMAPINFO *) buffer; bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfo->bmiHeader.biWidth = nSize.cx; bmpInfo->bmiHeader.biHeight = nSize.cy; bmpInfo->bmiHeader.biPlanes = 1; bmpInfo->bmiHeader.biBitCount = nDepth; bmpInfo->bmiHeader.biCompression = BI_RGB; bmpInfo->bmiHeader.biSizeImage = 0; bmpInfo->bmiHeader.biXPelsPerMeter = 0; bmpInfo->bmiHeader.biYPelsPerMeter = 0; bmpInfo->bmiHeader.biClrUsed = 0; bmpInfo->bmiHeader.biClrImportant = 0; bmpInfo->bmiColors[0].rgbBlue = 0; bmpInfo->bmiColors[0].rgbGreen = 0; bmpInfo->bmiColors[0].rgbRed = 0; bmpInfo->bmiColors[0].rgbReserved = 0; bitmap = CreateDIBSection(NIL, bmpInfo, DIB_RGB_COLORS, (Void **) &bytes, NIL, 0); delete [] buffer; if (bitmap == NIL) return False; size = nSize; depth = nDepth; bpp = depth; align = 4; return True; } S::Bool S::GUI::BitmapGDI::DeleteBitmap() { if (bitmap != NIL) { ::DeleteObject(bitmap); bitmap = NIL; size = Size(0, 0); depth = 0; bytes = NIL; bpp = 0; align = 0; } return True; } S::Bool S::GUI::BitmapGDI::SetSystemBitmap(Void *nBitmap) { if (nBitmap == GetSystemBitmap()) return True; if (nBitmap == NIL) { DeleteBitmap(); } else { BITMAP bmp; GetObject(nBitmap, sizeof(bmp), &bmp); CreateBitmap(Size(bmp.bmWidth, bmp.bmHeight), bmp.bmBitsPixel); HDC dc1 = CreateCompatibleDC(NIL); HDC dc2 = CreateCompatibleDC(NIL); HBITMAP backup1 = (HBITMAP) SelectObject(dc1, nBitmap); HBITMAP backup2 = (HBITMAP) SelectObject(dc2, bitmap); BitBlt(dc2, 0, 0, size.cx, size.cy, dc1, 0, 0, SRCCOPY); (HBITMAP) SelectObject(dc1, backup1); bitmap = (HBITMAP) SelectObject(dc2, backup2); DeleteDC(dc1); DeleteDC(dc2); } return True; } S::Void *S::GUI::BitmapGDI::GetSystemBitmap() const { return (Void *) bitmap; } S::Bool S::GUI::BitmapGDI::SetPixel(const Point &point, const Color &iColor) { if (bytes == NIL) return False; if (point.y >= size.cy || point.x >= size.cx) return False; Color color = iColor.ConvertTo(Color::RGBA); UnsignedByte *data = ((UnsignedByte *) bytes); Int offset = 0; switch (depth) { case 24: offset = (size.cy - point.y - 1) * (((4 - ((size.cx * 3) & 3)) & 3) + size.cx * 3) + point.x * 3; data[offset + 0] = (color >> 16) & 255; data[offset + 1] = (color >> 8) & 255; data[offset + 2] = color & 255; return True; case 32: offset = (size.cy - point.y - 1) * ( size.cx * 4) + point.x * 4; data[offset + 0] = (color >> 16) & 255; data[offset + 1] = (color >> 8) & 255; data[offset + 2] = color & 255; data[offset + 3] = (color >> 24) & 255; return True; } return False; } S::GUI::Color S::GUI::BitmapGDI::GetPixel(const Point &point) const { if (bytes == NIL) return 0; if (point.y >= size.cy || point.x >= size.cx) return 0; UnsignedByte *data = ((UnsignedByte *) bytes); Int offset = 0; switch (depth) { case 24: offset = (size.cy - point.y - 1) * (((4 - ((size.cx * 3) & 3)) & 3) + size.cx * 3) + point.x * 3; return Color( data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGB); case 32: offset = (size.cy - point.y - 1) * ( size.cx * 4) + point.x * 4; return Color(data[offset + 3] << 24 | data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGBA); } return 0; } S::GUI::BitmapBackend &S::GUI::BitmapGDI::operator =(const BitmapBackend &newBitmap) { if (&newBitmap == this) return *this; SetSystemBitmap(((BitmapGDI &) newBitmap).bitmap); return *this; } S::Bool S::GUI::BitmapGDI::operator ==(const int nil) const { if (bitmap == NIL) return True; else return False; } S::Bool S::GUI::BitmapGDI::operator !=(const int nil) const { if (bitmap == NIL) return False; else return True; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/fontgdi.cpp000077500000000000000000000056021516402577000256760ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include S::GUI::FontBackend *CreateFontGDI(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor) { return new S::GUI::FontGDI(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor); } S::Int fontGDITmp = S::GUI::FontBackend::SetBackend(&CreateFontGDI); S::Int addFontGDIInitTmp = S::AddInitFunction(&S::GUI::FontGDI::Initialize); S::Int S::GUI::FontGDI::Initialize() { NONCLIENTMETRICS ncm; ncm.cbSize = sizeof(ncm); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0); Font::Default = ncm.lfMessageFont.lfFaceName; Setup::FontSize = Float(-ncm.lfMessageFont.lfHeight) / 96.0 * 72.0 / Font::DefaultSize; return Success(); } S::GUI::FontGDI::FontGDI(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor) { type = FONT_GDI; } S::GUI::FontGDI::~FontGDI() { } S::GUI::Size S::GUI::FontGDI::GetTextSize(const String &text) const { if (text == NIL) return Size(); Int textLength = text.Length(); /* Fall back to Tahoma when trying to measure Hebrew on pre Windows 8 using Segoe UI. */ String fontName = this->fontName; if (fontName == "Segoe UI" && !Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2)) { for (Int i = 0; i < textLength; i++) if (text[i] >= 0x0590 && text[i] <= 0x05FF) { fontName = "Tahoma"; break; } } /* Check for right to left characters in text. */ Bool rtlCharacters = False; for (Int i = 0; i < textLength; i++) if (text[i] >= 0x0590 && text[i] <= 0x08FF) { rtlCharacters = True; break; } /* Set up Windows font and calculate text size. */ Float dpi = Surface().GetSurfaceDPI(); HDC dc = CreateCompatibleDC(NIL); HFONT hFont = CreateFont(-Math::Round(fontSize * dpi / 72.0), 0, 0, 0, fontWeight, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, FF_ROMAN, fontName); HFONT hOldFont = (HFONT) SelectObject(dc, hFont); RECT tRect; DrawTextEx(dc, text, -1, &tRect, DT_EXPANDTABS | DT_NOPREFIX | DT_LEFT | (rtlCharacters ? DT_RTLREADING : 0) | DT_CALCRECT, NIL); SelectObject(dc, hOldFont); ::DeleteObject(hFont); DeleteDC(dc); return Size(tRect.right - tRect.left, tRect.bottom - tRect.top); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/surfacegdi.cpp000077500000000000000000000432411516402577000263610ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include S::GUI::SurfaceBackend *CreateSurfaceGDI(S::Void *iSurface, const S::GUI::Size &maxSize) { return new S::GUI::SurfaceGDI(iSurface, maxSize); } S::Int surfaceGDITmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceGDI); S::Short S::GUI::SurfaceGDI::surfaceDPI = -1; S::GUI::SurfaceGDI::SurfaceGDI(Void *iWindow, const Size &maxSize) { type = SURFACE_GDI; window = (HWND) iWindow; paintBitmap = NIL; paintContext = NIL; if (window != NIL) { HDC gdi_dc = GetWindowDC(window); size = maxSize; if (maxSize == Size()) { size.cx = GetDeviceCaps(gdi_dc, HORZRES) + 2; size.cy = GetDeviceCaps(gdi_dc, VERTRES) + 2; } fontSize.SetFontSize(GetSurfaceDPI()); rightToLeft.SetSurfaceSize(size); paintContext = CreateCompatibleDC(gdi_dc); HBITMAP bitmap = CreateCompatibleBitmap(gdi_dc, size.cx, size.cy); paintBitmap = (HBITMAP) SelectObject(paintContext, bitmap); paintRects.Add(Rect(Point(0, 0), size)); ReleaseDC(window, gdi_dc); allocSize = size; } } S::GUI::SurfaceGDI::~SurfaceGDI() { if (window != NIL) { HBITMAP bitmap = (HBITMAP) SelectObject(paintContext, paintBitmap); DeleteDC(paintContext); ::DeleteObject(bitmap); } } S::Int S::GUI::SurfaceGDI::SetSize(const Size &nSize) { size = nSize; rightToLeft.SetSurfaceSize(size); if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success(); if (window != NIL && !painting) { HBITMAP bitmap = (HBITMAP) SelectObject(paintContext, paintBitmap); ::DeleteObject(bitmap); paintRects.RemoveAll(); HDC gdi_dc = GetWindowDC(window); bitmap = CreateCompatibleBitmap(gdi_dc, size.cx, size.cy); paintBitmap = (HBITMAP) SelectObject(paintContext, bitmap); paintRects.Add(Rect(Point(0, 0), size)); ReleaseDC(window, gdi_dc); } allocSize = nSize; return Success(); } const S::GUI::Size &S::GUI::SurfaceGDI::GetSize() const { return size; } S::Int S::GUI::SurfaceGDI::PaintRect(const Rect &pRect) { if (painting) return Error(); if (window != NIL) { HDC gdi_dc = GetWindowDC(window); BitBlt(gdi_dc, pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight(), paintContext, pRect.left, pRect.top, SRCCOPY); ReleaseDC(window, gdi_dc); } return Success(); } S::Int S::GUI::SurfaceGDI::StartPaint(const Rect &iPRect) { if (window == NIL) return Success(); Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast()); HRGN region = CreateRectRgn(pRect.left, pRect.top, pRect.right, pRect.bottom); SaveDC(paintContext); SelectClipRgn(paintContext, region); ::DeleteObject(region); paintRects.Add(pRect); painting++; return Success(); } S::Int S::GUI::SurfaceGDI::EndPaint() { if (!painting) return Error(); painting--; if (painting == 0) PaintRect(paintRects.GetLast()); paintRects.RemoveNth(paintRects.Length() - 1); RestoreDC(paintContext, -1); return Success(); } S::Void *S::GUI::SurfaceGDI::GetSystemSurface() const { return (Void *) window; } S::Short S::GUI::SurfaceGDI::GetSurfaceDPI() const { if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor()); if (surfaceDPI != -1) return surfaceDPI; Float dpi = 96.0; surfaceDPI = Math::Round(dpi * Setup::FontSize); return surfaceDPI; } S::Int S::GUI::SurfaceGDI::SetPixel(const Point &iPoint, const Color &color) { if (window == NIL) return Success(); Point point = rightToLeft.TranslatePoint(iPoint); if (!painting) { HDC gdi_dc = GetWindowDC(window); ::SetPixel(gdi_dc, point.x, point.y, color); ReleaseDC(window, gdi_dc); } ::SetPixel(paintContext, point.x, point.y, color); return Success(); } S::Int S::GUI::SurfaceGDI::Line(const Point &iPos1, const Point &iPos2, const Color &color) { if (window == NIL) return Success(); Point pos1 = rightToLeft.TranslatePoint(iPos1); Point pos2 = rightToLeft.TranslatePoint(iPos2); HPEN hPen = CreatePen(PS_SOLID, 1, color); HPEN hOldPen = NIL; if (!painting) { HDC gdi_dc = GetWindowDC(window); hOldPen = (HPEN) SelectObject(gdi_dc, hPen); MoveToEx(gdi_dc, pos1.x, pos1.y, NIL); LineTo(gdi_dc, pos2.x, pos2.y); hPen = (HPEN) SelectObject(gdi_dc, hOldPen); ReleaseDC(window, gdi_dc); } hOldPen = (HPEN) SelectObject(paintContext, hPen); MoveToEx(paintContext, pos1.x, pos1.y, NIL); LineTo(paintContext, pos2.x, pos2.y); hPen = (HPEN) SelectObject(paintContext, hOldPen); ::DeleteObject(hPen); return Success(); } S::Int S::GUI::SurfaceGDI::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse) { if (window == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect); HDC gdi_dc = painting ? NIL : GetWindowDC(window); HBRUSH brush = CreateSolidBrush(color); RECT wRect = { rect.left, rect.top, rect.right, rect.bottom }; if (style & Rect::Filled) { if (style & Rect::Rounded) { HPEN pen = CreatePen(PS_SOLID, 0, color); if (!painting) { HBRUSH previousBrush = (HBRUSH) SelectObject(gdi_dc, brush); HPEN previousPen = (HPEN) SelectObject(gdi_dc, pen); RoundRect(gdi_dc, rect.left, rect.top, rect.right, rect.bottom, ellipse.cx, ellipse.cy); brush = (HBRUSH) SelectObject(gdi_dc, previousBrush); pen = (HPEN) SelectObject(gdi_dc, previousPen); } HBRUSH previousBrush = (HBRUSH) SelectObject(paintContext, brush); HPEN previousPen = (HPEN) SelectObject(paintContext, pen); RoundRect(paintContext, rect.left, rect.top, rect.right, rect.bottom, ellipse.cx, ellipse.cy); brush = (HBRUSH) SelectObject(paintContext, previousBrush); pen = (HPEN) SelectObject(paintContext, previousPen); ::DeleteObject(pen); } else { if (!painting) FillRect(gdi_dc, &wRect, brush); FillRect(paintContext, &wRect, brush); } } else if (style == Rect::Outlined) { if (!painting) FrameRect(gdi_dc, &wRect, brush); FrameRect(paintContext, &wRect, brush); } else if (style & Rect::Inverted) { if (!painting) InvertRect(gdi_dc, &wRect); InvertRect(paintContext, &wRect); } else if (style & Rect::Dotted) { if (!painting) { for (Int x = rect.left + 1; x < rect.right; x += 2) ::SetPixel(gdi_dc, x, rect.top, color); for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) ::SetPixel(gdi_dc, rect.right - 1, y, color); for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) ::SetPixel(gdi_dc, x, rect.bottom - 1, color); for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) ::SetPixel(gdi_dc, rect.left, y, color); } for (Int x = rect.left + 1; x < rect.right; x += 2) ::SetPixel(paintContext, x, rect.top, color); for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) ::SetPixel(paintContext, rect.right - 1, y, color); for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) ::SetPixel(paintContext, x, rect.bottom - 1, color); for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) ::SetPixel(paintContext, rect.left, y, color); } ::DeleteObject(brush); if (!painting) ReleaseDC(window, gdi_dc); return Success(); } S::Int S::GUI::SurfaceGDI::SetText(const String &string, const Rect &iRect, const Font &iFont, Bool shadow) { if (window == NIL) return Success(); if (string == NIL) return Error(); if (shadow) return SurfaceBackend::SetText(string, iRect, iFont, shadow); Int stringLength = string.Length(); Font font = iFont; Rect rect = iRect; Int lineHeight = 0; /* Fall back to Tahoma when trying to draw Hebrew on pre Windows 8 using Segoe UI. */ if (font.GetName() == "Segoe UI" && !Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2)) { for (Int i = 0; i < stringLength; i++) if (string[i] >= 0x0590 && string[i] <= 0x05FF) { font.SetName("Tahoma"); break; } } /* Set up Windows font. */ HDC gdi_dc = painting ? NIL : GetWindowDC(window); HFONT hfont = CreateFont(-Math::Round(font.GetSize() * fontSize.TranslateY(96) / 72.0), 0, 0, 0, font.GetWeight(), font.GetStyle() & Font::Italic, font.GetStyle() & Font::Underline, font.GetStyle() & Font::StrikeOut, ANSI_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, FF_ROMAN, font.GetName()); HFONT holdfont = NIL; HFONT holdfont2 = NIL; if (!painting) { SetBkMode(gdi_dc, TRANSPARENT); SetTextColor(gdi_dc, font.GetColor()); holdfont = (HFONT) SelectObject(gdi_dc, hfont); } SetBkMode(paintContext, TRANSPARENT); SetTextColor(paintContext, font.GetColor()); holdfont2 = (HFONT) SelectObject(paintContext, hfont); /* Draw text line by line. */ const Array &lines = string.Explode("\n"); if (lines.Length() > 1) lineHeight = font.GetScaledTextSizeY() + 3; foreach (const String &line, lines) { Int lineLength = line.Length(); /* Check for right to left characters in text. */ Bool rtlCharacters = False; for (Int i = 0; i < lineLength; i++) if (line[i] >= 0x0590 && line[i] <= 0x08FF) { rtlCharacters = True; break; } /* Draw text, reordering if necessary. */ Rect tRect = rightToLeft.TranslateRect(rect); RECT wRect = { tRect.left, tRect.top, tRect.right, tRect.bottom }; if (rtlCharacters && Setup::useIconv) { String visualLine; /* Reorder the string with fribidi, then get * the glyph indices using GetCharacterPlacement * and display using the glyph indices. * This does not work with Kanji. */ FriBidiChar *visual = new FriBidiChar [lineLength + 1]; FriBidiParType type = (rightToLeft.GetRightToLeft() ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR); fribidi_log2vis((FriBidiChar *) line.ConvertTo("UCS-4LE"), lineLength, &type, visual, NIL, NIL, NIL); visual[lineLength] = 0; visualLine.ImportFrom("UCS-4LE", (char *) visual); delete [] visual; GCP_RESULTS results; wchar_t *glyphs = new wchar_t [lineLength + 1]; ZeroMemory(&results, sizeof(results)); results.lStructSize = sizeof(results); results.lpGlyphs = glyphs; results.nGlyphs = lineLength + 1; ZeroMemory(glyphs, 2 * (lineLength + 1)); if (!painting) { if (rightToLeft.GetRightToLeft()) SetTextAlign(gdi_dc, TA_RIGHT); else SetTextAlign(gdi_dc, TA_LEFT); } if (rightToLeft.GetRightToLeft()) SetTextAlign(paintContext, TA_RIGHT); else SetTextAlign(paintContext, TA_LEFT); GetCharacterPlacement(paintContext, visualLine, lineLength, 0, &results, 0); if (rightToLeft.GetRightToLeft()) wRect.left -= 10; else wRect.right += 10; if (!painting) ExtTextOut(gdi_dc, (rightToLeft.GetRightToLeft() ? wRect.right : wRect.left), wRect.top, ETO_CLIPPED | ETO_GLYPH_INDEX, &wRect, results.lpGlyphs, results.nGlyphs, NIL); ExtTextOut(paintContext, (rightToLeft.GetRightToLeft() ? wRect.right : wRect.left), wRect.top, ETO_CLIPPED | ETO_GLYPH_INDEX, &wRect, results.lpGlyphs, results.nGlyphs, NIL); delete [] glyphs; } else { /* Let Windows do any reordering and ligating. * Works with Kanji, but RTL is only supported * on XP and later versions of Windows and even * later versions get the base direction wrong. */ if (!painting) { SetTextAlign(gdi_dc, TA_LEFT); DrawTextEx(gdi_dc, line, -1, &wRect, DT_EXPANDTABS | DT_NOPREFIX | (rightToLeft.GetRightToLeft() ? DT_RIGHT : DT_LEFT) | (rtlCharacters ? DT_RTLREADING : 0), NIL); } SetTextAlign(paintContext, TA_LEFT); DrawTextEx(paintContext, line, -1, &wRect, DT_EXPANDTABS | DT_NOPREFIX | (rightToLeft.GetRightToLeft() ? DT_RIGHT : DT_LEFT) | (rtlCharacters ? DT_RTLREADING : 0), NIL); } rect.top += lineHeight; } if (!painting) { SelectObject(gdi_dc, holdfont); ReleaseDC(window, gdi_dc); } SelectObject(paintContext, holdfont2); ::DeleteObject(hfont); return Success(); } S::Int S::GUI::SurfaceGDI::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style) { if (window == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect); /* Setup colors. */ Color c1 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color2 : color1; Color c2 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color1 : color2; /* Setup GDI structures and draw gradient. */ GRADIENT_RECT rects[1] = { { 0, 1 } }; TRIVERTEX vertices[2] = { { rect.left, rect.top, COLOR16(c1.GetRed() << 8), COLOR16(c1.GetGreen() << 8), COLOR16(c1.GetBlue() << 8), 0 }, { rect.right, rect.bottom, COLOR16(c2.GetRed() << 8), COLOR16(c2.GetGreen() << 8), COLOR16(c2.GetBlue() << 8), 0 } }; if (!painting) { HDC gdi_dc = GetWindowDC(window); if (style == OR_HORZ) GdiGradientFill(gdi_dc, vertices, 2, rects, 1, GRADIENT_FILL_RECT_H); else GdiGradientFill(gdi_dc, vertices, 2, rects, 1, GRADIENT_FILL_RECT_V); ReleaseDC(window, gdi_dc); } if (style == OR_HORZ) GdiGradientFill(paintContext, vertices, 2, rects, 1, GRADIENT_FILL_RECT_H); else GdiGradientFill(paintContext, vertices, 2, rects, 1, GRADIENT_FILL_RECT_V); return Success(); } S::Int S::GUI::SurfaceGDI::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect destRect = rightToLeft.TranslateRect(iDestRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ HDC gdi_dc = painting ? NIL : GetWindowDC(window); HDC cdc = CreateCompatibleDC(paintContext); BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; Bitmap premultipliedBitmap = bitmap; PremultiplyAlpha(premultipliedBitmap); if (destRect.GetSize() == srcRect.GetSize()) { HBITMAP backup = (HBITMAP) SelectObject(cdc, premultipliedBitmap.GetSystemBitmap()); if (!painting) { if (bitmap.GetDepth() == 32) AlphaBlend(gdi_dc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), blend); else BitBlt(gdi_dc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, srcRect.left, srcRect.top, SRCCOPY); } if (bitmap.GetDepth() == 32) AlphaBlend(paintContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), blend); else BitBlt(paintContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, srcRect.left, srcRect.top, SRCCOPY); SelectObject(cdc, backup); } else { Float scaleFactorX = Float(srcRect.GetWidth()) / Float(destRect.GetWidth()); Float scaleFactorY = Float(srcRect.GetHeight()) / Float(destRect.GetHeight()); Size srcSize = premultipliedBitmap.GetSize(); const Bitmap &srcBitmap = premultipliedBitmap.Scale(Size(Float(srcSize.cx) / scaleFactorX, Float(srcSize.cy) / scaleFactorY)); HBITMAP backup = (HBITMAP) SelectObject(cdc, srcBitmap.GetSystemBitmap()); if (!painting) { if (bitmap.GetDepth() == 32) AlphaBlend(gdi_dc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, Float(srcRect.GetWidth()) / scaleFactorX, Float(srcRect.GetHeight()) / scaleFactorY, blend); else BitBlt(gdi_dc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, SRCCOPY); } if (bitmap.GetDepth() == 32) AlphaBlend(paintContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, Float(srcRect.GetWidth()) / scaleFactorX, Float(srcRect.GetHeight()) / scaleFactorY, blend); else BitBlt(paintContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, SRCCOPY); SelectObject(cdc, backup); } DeleteDC(cdc); if (!painting) ReleaseDC(window, gdi_dc); return Success(); } S::Int S::GUI::SurfaceGDI::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect srcRect = rightToLeft.TranslateRect(iSrcRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ HDC cdc = CreateCompatibleDC(paintContext); HBITMAP backup = (HBITMAP) SelectObject(cdc, bitmap.GetSystemBitmap()); if (destRect.GetSize() == srcRect.GetSize()) { BitBlt(cdc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), paintContext, srcRect.left, srcRect.top, SRCCOPY); } else { SetStretchBltMode(cdc, HALFTONE); StretchBlt(cdc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), paintContext, srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), SRCCOPY); } SelectObject(cdc, backup); DeleteDC(cdc); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/000077500000000000000000000000001516402577000244365ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/Makefile000066400000000000000000000007161516402577000261020ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_GDIPLUS),True) OBJECTS += bitmapgdiplus.o fontgdiplus.o surfacegdiplus.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/bitmapgdiplus.cpp000077500000000000000000000126651516402577000300230ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::GUI::BitmapBackend *CreateBitmapGDIPlus_pV(S::Void *iBitmap) { return new S::GUI::BitmapGDIPlus(iBitmap); } S::GUI::BitmapBackend *CreateBitmapGDIPlus_crSI(const S::GUI::Size &iSize, S::Int iDepth) { return new S::GUI::BitmapGDIPlus(iSize, iDepth); } S::GUI::BitmapBackend *CreateBitmapGDIPlus_cI(const int nil) { return new S::GUI::BitmapGDIPlus(nil); } S::GUI::BitmapBackend *CreateBitmapGDIPlus_crB(const S::GUI::BitmapBackend &iBitmap) { return new S::GUI::BitmapGDIPlus((const S::GUI::BitmapGDIPlus &) iBitmap); } S::Int bitmapGDIPlusTmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDIPlus_pV); S::Int bitmapGDIPlusTmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDIPlus_crSI); S::Int bitmapGDIPlusTmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDIPlus_cI); S::Int bitmapGDIPlusTmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDIPlus_crB); S::GUI::BitmapGDIPlus::BitmapGDIPlus(Void *iBitmap) { type = BITMAP_GDIPLUS; bitmap = NIL; hBitmap = NIL; SetSystemBitmap(iBitmap); } S::GUI::BitmapGDIPlus::BitmapGDIPlus(const Size &iSize, Int iDepth) { type = BITMAP_GDIPLUS; bitmap = NIL; hBitmap = NIL; CreateBitmap(iSize, iDepth); } S::GUI::BitmapGDIPlus::BitmapGDIPlus(const int nil) { type = BITMAP_GDIPLUS; bitmap = NIL; hBitmap = NIL; SetSystemBitmap(NIL); } S::GUI::BitmapGDIPlus::BitmapGDIPlus(const BitmapGDIPlus &iBitmap) { type = BITMAP_GDIPLUS; bitmap = NIL; hBitmap = NIL; if (iBitmap != NIL) { CreateBitmap(iBitmap.GetSize(), iBitmap.GetDepth()); memcpy(bytes, iBitmap.GetBytes(), (bpp / 8) * size.cx * size.cy); } } S::GUI::BitmapGDIPlus::~BitmapGDIPlus() { DeleteBitmap(); } S::Bool S::GUI::BitmapGDIPlus::CreateBitmap(const Size &nSize, Int nDepth) { DeleteBitmap(); if (nDepth == -1) nDepth = 32; if (nDepth != 32) nDepth = 32; bytes = new UnsignedByte [(nDepth / 8) * nSize.cx * nSize.cy]; bitmap = new Gdiplus::Bitmap(nSize.cx, nSize.cy, nSize.cx * (nDepth / 8), PixelFormat32bppARGB, (BYTE *) bytes); if (bitmap == NIL) return False; size = nSize; depth = nDepth; bpp = depth; align = 4; return True; } S::Bool S::GUI::BitmapGDIPlus::DeleteBitmap() { if (bitmap != NIL) { delete bitmap; if (hBitmap != NIL) ::DeleteObject(hBitmap); bitmap = NIL; hBitmap = NIL; size = Size(0, 0); depth = 0; delete [] (UnsignedByte *) bytes; bytes = NIL; bpp = 0; align = 0; } return True; } S::Bool S::GUI::BitmapGDIPlus::SetSystemBitmap(Void *nBitmap) { if (nBitmap == GetSystemBitmap()) return True; if (nBitmap == NIL) { DeleteBitmap(); } else { Gdiplus::Bitmap *gdipBitmap = (Gdiplus::Bitmap *) nBitmap; CreateBitmap(Size(gdipBitmap->GetWidth(), gdipBitmap->GetHeight()), 32); Gdiplus::Graphics graphics(bitmap); graphics.DrawImage(gdipBitmap, 0, 0, gdipBitmap->GetWidth(), gdipBitmap->GetHeight()); } return True; } S::Void *S::GUI::BitmapGDIPlus::GetSystemBitmap() const { return (Void *) bitmap; } S::Bool S::GUI::BitmapGDIPlus::SetPixel(const Point &point, const Color &iColor) { if (bytes == NIL) return False; if (point.y >= size.cy || point.x >= size.cx) return False; Color color = iColor.ConvertTo(Color::RGBA); UnsignedByte *data = ((UnsignedByte *) bytes); Int offset = 0; switch (depth) { case 24: offset = point.y * (((4 - ((size.cx * 3) & 3)) & 3) + size.cx * 3) + point.x * 3; data[offset + 0] = (color >> 16) & 255; data[offset + 1] = (color >> 8) & 255; data[offset + 2] = color & 255; return True; case 32: offset = point.y * ( size.cx * 4) + point.x * 4; data[offset + 0] = (color >> 16) & 255; data[offset + 1] = (color >> 8) & 255; data[offset + 2] = color & 255; data[offset + 3] = (color >> 24) & 255; return True; } return False; } S::GUI::Color S::GUI::BitmapGDIPlus::GetPixel(const Point &point) const { if (bytes == NIL) return 0; if (point.y >= size.cy || point.x >= size.cx) return 0; UnsignedByte *data = ((UnsignedByte *) bytes); Int offset = 0; switch (depth) { case 24: offset = point.y * (((4 - ((size.cx * 3) & 3)) & 3) + size.cx * 3) + point.x * 3; return Color( data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGB); case 32: offset = point.y * ( size.cx * 4) + point.x * 4; return Color(data[offset + 3] << 24 | data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGBA); } return 0; } S::GUI::BitmapBackend &S::GUI::BitmapGDIPlus::operator =(const BitmapBackend &newBitmap) { if (&newBitmap == this) return *this; DeleteBitmap(); if (newBitmap != NIL) { CreateBitmap(newBitmap.GetSize(), newBitmap.GetDepth()); memcpy(bytes, newBitmap.GetBytes(), (bpp / 8) * size.cx * size.cy); } return *this; } S::Bool S::GUI::BitmapGDIPlus::operator ==(const int nil) const { if (bitmap == NIL) return True; else return False; } S::Bool S::GUI::BitmapGDIPlus::operator !=(const int nil) const { if (bitmap == NIL) return False; else return True; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/fontgdiplus.cpp000077500000000000000000000054051516402577000275070ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include S::GUI::FontBackend *CreateFontGDIPlus(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor) { return new S::GUI::FontGDIPlus(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor); } S::Int fontGDIPlusTmp = S::GUI::FontBackend::SetBackend(&CreateFontGDIPlus); S::Int addFontGDIPlusInitTmp = S::AddInitFunction(&S::GUI::FontGDIPlus::Initialize); S::Int S::GUI::FontGDIPlus::Initialize() { NONCLIENTMETRICS ncm; ncm.cbSize = sizeof(ncm); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0); Font::Default = ncm.lfMessageFont.lfFaceName; Setup::FontSize = Float(-ncm.lfMessageFont.lfHeight) / 96.0 * 72.0 / Font::DefaultSize; return Success(); } S::GUI::FontGDIPlus::FontGDIPlus(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor) { type = FONT_GDIPLUS; } S::GUI::FontGDIPlus::~FontGDIPlus() { } S::GUI::Size S::GUI::FontGDIPlus::GetTextSize(const String &text) const { if (text == NIL) return Size(); Int textLength = text.Length(); /* Fall back to Tahoma when trying to measure Hebrew on pre Windows 8 using Segoe UI. */ String fontName = this->fontName; if (fontName == "Segoe UI" && !Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2)) { for (Int i = 0; i < textLength; i++) if (text[i] >= 0x0590 && text[i] <= 0x05FF) { fontName = "Tahoma"; break; } } /* Set up GDI+ font and calculate text size. */ Float dpi = Surface().GetSurfaceDPI(); Gdiplus::Graphics gdip_context((HWND) NIL); Gdiplus::Font gdip_font(fontName, fontSize * dpi / 96.0, fontWeight >= Font::Bold ? Gdiplus::FontStyleBold : Gdiplus::FontStyleRegular); Gdiplus::StringFormat gdip_format(Gdiplus::StringFormatFlagsNoWrap | Gdiplus::StringFormatFlagsMeasureTrailingSpaces); Gdiplus::RectF gdip_rect; gdip_format.SetAlignment(Gdiplus::StringAlignmentNear); gdip_context.MeasureString(text, -1, &gdip_font, Gdiplus::PointF(0.0, 0.0), &gdip_format, &gdip_rect); return Size(gdip_rect.Width, gdip_rect.Height - 2); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/surfacegdiplus.cpp000077500000000000000000000356011516402577000301720ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include S::GUI::SurfaceBackend *CreateSurfaceGDIPlus(S::Void *iSurface, const S::GUI::Size &maxSize) { return new S::GUI::SurfaceGDIPlus(iSurface, maxSize); } S::Int surfaceGDIPlusTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceGDIPlus); S::Short S::GUI::SurfaceGDIPlus::surfaceDPI = -1; S::GUI::SurfaceGDIPlus::SurfaceGDIPlus(Void *iWindow, const Size &maxSize) { type = SURFACE_GDIPLUS; window = (HWND) iWindow; paintBitmap = NIL; paintContext = NIL; if (window != NIL) { HDC gdi_dc = GetWindowDC(window); size = maxSize; if (maxSize == Size()) { size.cx = GetDeviceCaps(gdi_dc, HORZRES) + 2; size.cy = GetDeviceCaps(gdi_dc, VERTRES) + 2; } fontSize.SetFontSize(GetSurfaceDPI()); rightToLeft.SetSurfaceSize(size); Gdiplus::Graphics *graphics = new Gdiplus::Graphics(gdi_dc); paintBitmap = new Gdiplus::Bitmap(size.cx, size.cy, graphics); paintContext = new Gdiplus::Graphics(paintBitmap); paintRects.Add(Rect(Point(0, 0), size)); delete graphics; ReleaseDC(window, gdi_dc); allocSize = size; } } S::GUI::SurfaceGDIPlus::~SurfaceGDIPlus() { if (window != NIL) { delete paintContext; delete paintBitmap; } } S::Int S::GUI::SurfaceGDIPlus::SetSize(const Size &nSize) { size = nSize; rightToLeft.SetSurfaceSize(size); if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success(); if (window != NIL && !painting) { delete paintContext; delete paintBitmap; paintRects.RemoveAll(); HDC gdi_dc = GetWindowDC(window); Gdiplus::Graphics *graphics = new Gdiplus::Graphics(gdi_dc); paintBitmap = new Gdiplus::Bitmap(size.cx, size.cy, graphics); paintContext = new Gdiplus::Graphics(paintBitmap); paintRects.Add(Rect(Point(0, 0), size)); delete graphics; ReleaseDC(window, gdi_dc); } allocSize = nSize; return Success(); } const S::GUI::Size &S::GUI::SurfaceGDIPlus::GetSize() const { return size; } S::Int S::GUI::SurfaceGDIPlus::PaintRect(const Rect &pRect) { if (painting) return Error(); if (window != NIL) { HDC gdi_dc = GetWindowDC(window); Gdiplus::Graphics *graphics = new Gdiplus::Graphics(gdi_dc); Gdiplus::RectF srcRect(pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight()); Gdiplus::RectF destRect(pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight()); graphics->DrawImage(paintBitmap, destRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel); delete graphics; ReleaseDC(window, gdi_dc); } return Success(); } S::Int S::GUI::SurfaceGDIPlus::StartPaint(const Rect &iPRect) { if (window == NIL) return Success(); Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast()); paintStates.Add(paintContext->Save()); paintRects.Add(pRect); paintContext->SetClip(Gdiplus::Rect(pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight())); painting++; return Success(); } S::Int S::GUI::SurfaceGDIPlus::EndPaint() { if (!painting) return Error(); painting--; if (painting == 0) PaintRect(paintRects.GetLast()); paintContext->Restore(paintStates.GetLast()); paintRects.RemoveNth(paintRects.Length() - 1); paintStates.RemoveNth(paintStates.Length() - 1); return Success(); } S::Void *S::GUI::SurfaceGDIPlus::GetSystemSurface() const { return (Void *) window; } S::Short S::GUI::SurfaceGDIPlus::GetSurfaceDPI() const { if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor()); if (surfaceDPI != -1) return surfaceDPI; Float dpi = 96.0; surfaceDPI = Math::Round(dpi * Setup::FontSize); return surfaceDPI; } S::Int S::GUI::SurfaceGDIPlus::SetPixel(const Point &iPoint, const Color &color) { if (window == NIL) return Success(); Point point = rightToLeft.TranslatePoint(iPoint); Gdiplus::Bitmap bitmap(1, 1); bitmap.SetPixel(0, 0, Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue())); if (!painting) { HDC gdi_dc = GetWindowDC(window); Gdiplus::Graphics *pGraphics = new Gdiplus::Graphics(gdi_dc); pGraphics->DrawImage(&bitmap, point.x, point.y); delete pGraphics; ReleaseDC(window, gdi_dc); } paintContext->DrawImage(&bitmap, point.x, point.y); return Success(); } S::Int S::GUI::SurfaceGDIPlus::Line(const Point &iPos1, const Point &iPos2, const Color &color) { if (window == NIL) return Success(); Point pos1 = rightToLeft.TranslatePoint(iPos1); Point pos2 = rightToLeft.TranslatePoint(iPos2); /* Adjust to Windows GDI behavior for diagonal lines. */ if (Math::Abs(pos2.x - pos1.x) == Math::Abs(pos2.y - pos1.y)) { if (pos1.x < pos2.x) pos2.x--; else if (pos1.x > pos2.x) pos2.x++; if (pos1.y < pos2.y) pos2.y--; else if (pos1.y > pos2.y) pos2.y++; } /* Adjust to Windows GDI behaviour for horizontal and vertical lines. */ if (pos1.x == pos2.x && pos1.y < pos2.y) pos2.y--; if (pos1.x == pos2.x && pos1.y > pos2.y) pos1.y--; if (pos1.y == pos2.y && pos1.x < pos2.x) pos2.x--; if (pos1.y == pos2.y && pos1.x > pos2.x) pos1.x--; if (pos1 == pos2) return SetPixel(rightToLeft.TranslatePoint(pos1), color); Gdiplus::Pen pen(Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue())); if (!painting) { HDC gdi_dc = GetWindowDC(window); Gdiplus::Graphics *pGraphics = new Gdiplus::Graphics(gdi_dc); pGraphics->DrawLine(&pen, pos1.x, pos1.y, pos2.x, pos2.y); delete pGraphics; ReleaseDC(window, gdi_dc); } paintContext->DrawLine(&pen, pos1.x, pos1.y, pos2.x, pos2.y); return Success(); } S::Int S::GUI::SurfaceGDIPlus::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse) { if (window == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect); Gdiplus::SolidBrush gdip_brush(Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue())); Gdiplus::Pen gdip_pen(Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue())); Gdiplus::Rect gdip_rect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); HDC gdi_dc = NIL; Gdiplus::Graphics *pGraphics = NIL; if (!painting) { gdi_dc = GetWindowDC(window); pGraphics = new Gdiplus::Graphics(gdi_dc); } if (style & Rect::Filled) { if (style & Rect::Rounded) { /* ToDo: Allow drawing of rounded rects. */ } else { if (!painting) pGraphics->FillRectangle(&gdip_brush, gdip_rect); paintContext->FillRectangle(&gdip_brush, gdip_rect); } } else if (style == Rect::Outlined) { gdip_rect.Width--; gdip_rect.Height--; if (!painting) pGraphics->DrawRectangle(&gdip_pen, gdip_rect); paintContext->DrawRectangle(&gdip_pen, gdip_rect); } else if (style & Rect::Inverted) { Bitmap area(rect.GetSize()); BlitToBitmap(iRect, area, Rect(Point(0, 0), area.GetSize())); area.InvertColors(); BlitFromBitmap(area, Rect(Point(0, 0), area.GetSize()), iRect); } else if (style & Rect::Dotted) { if (!painting) { for (Int x = rect.left + 1; x < rect.right; x += 2) pGraphics->DrawLine(&gdip_pen, x, rect.top, x, rect.top - 1); for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) pGraphics->DrawLine(&gdip_pen, rect.right - 1, y, rect.right, y); for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) pGraphics->DrawLine(&gdip_pen, x, rect.bottom - 1, x, rect.bottom); for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) pGraphics->DrawLine(&gdip_pen, rect.left, y, rect.left - 1, y); } for (Int x = rect.left + 1; x < rect.right; x += 2) paintContext->DrawLine(&gdip_pen, x, rect.top, x, rect.top - 1); for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) paintContext->DrawLine(&gdip_pen, rect.right - 1, y, rect.right, y); for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) paintContext->DrawLine(&gdip_pen, x, rect.bottom - 1, x, rect.bottom); for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) paintContext->DrawLine(&gdip_pen, rect.left, y, rect.left - 1, y); } if (!painting) { delete pGraphics; ReleaseDC(window, gdi_dc); } return Success(); } S::Int S::GUI::SurfaceGDIPlus::SetText(const String &string, const Rect &iRect, const Font &iFont, Bool shadow) { if (window == NIL) return Success(); if (string == NIL) return Error(); if (shadow) return SurfaceBackend::SetText(string, iRect, iFont, shadow); Int stringLength = string.Length(); Font font = iFont; Rect rect = iRect; Int lineHeight = 0; Color color = font.GetColor(); /* Fall back to Tahoma when trying to draw Hebrew on pre Windows 8 using Segoe UI. */ if (font.GetName() == "Segoe UI" && !Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2)) { for (Int i = 0; i < stringLength; i++) if (string[i] >= 0x0590 && string[i] <= 0x05FF) { font.SetName("Tahoma"); break; } } /* Set up GDI+ font. */ Gdiplus::Font gdip_font(font.GetName(), fontSize.TranslateY(font.GetSize()), (font.GetWeight() >= Font::Bold ? Gdiplus::FontStyleBold : Gdiplus::FontStyleRegular) | (font.GetStyle() & Font::Italic ? Gdiplus::FontStyleItalic : Gdiplus::FontStyleRegular) | (font.GetStyle() & Font::Underline ? Gdiplus::FontStyleUnderline : Gdiplus::FontStyleRegular) | (font.GetStyle() & Font::StrikeOut ? Gdiplus::FontStyleStrikeout : Gdiplus::FontStyleRegular)); Gdiplus::SolidBrush gdip_brush(Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue())); Gdiplus::StringFormat gdip_format(Gdiplus::StringFormatFlagsNoWrap); HDC gdi_dc = NIL; Gdiplus::Graphics *pGraphics = NIL; if (!painting) { gdi_dc = GetWindowDC(window); pGraphics = new Gdiplus::Graphics(gdi_dc); } /* Draw text line by line. */ const Array &lines = string.Explode("\n"); if (lines.Length() > 1) lineHeight = font.GetScaledTextSizeY() + 3; foreach (const String &line, lines) { Int lineLength = line.Length(); /* Check for right to left characters in text. */ Bool rtlCharacters = False; for (Int i = 0; i < lineLength; i++) if (line[i] >= 0x0590 && line[i] <= 0x08FF) { rtlCharacters = True; break; } Rect tRect = rightToLeft.TranslateRect(rect); Gdiplus::RectF gdip_rect(tRect.left, tRect.top, tRect.GetWidth() + 2, tRect.GetHeight()); if (rtlCharacters) gdip_format.SetFormatFlags(Gdiplus::StringFormatFlagsNoWrap | Gdiplus::StringFormatFlagsDirectionRightToLeft); else gdip_format.SetFormatFlags(Gdiplus::StringFormatFlagsNoWrap); if ((!rtlCharacters && rightToLeft.GetRightToLeft()) || ( rtlCharacters && !rightToLeft.GetRightToLeft())) gdip_format.SetAlignment(Gdiplus::StringAlignmentFar); else gdip_format.SetAlignment(Gdiplus::StringAlignmentNear); if (!painting) pGraphics->DrawString(line, -1, &gdip_font, gdip_rect, &gdip_format, &gdip_brush); paintContext->DrawString(line, -1, &gdip_font, gdip_rect, &gdip_format, &gdip_brush); rect.top += lineHeight; } if (!painting) { delete pGraphics; ReleaseDC(window, gdi_dc); } return Success(); } S::Int S::GUI::SurfaceGDIPlus::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style) { if (window == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect); /* Setup colors. */ Color c1 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color2 : color1; Color c2 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color1 : color2; /* Setup GDI+ objects and draw gradient. */ Gdiplus::LinearGradientBrush gdip_brush(Gdiplus::Point(rect.left, rect.top), Gdiplus::Point(rect.left + (style == OR_HORZ ? rect.GetWidth() : 0), rect.top + (style == OR_VERT ? rect.GetHeight() : 0)), Gdiplus::Color(c1.GetRed(), c1.GetGreen(), c1.GetBlue()), Gdiplus::Color(c2.GetRed(), c2.GetGreen(), c2.GetBlue())); Gdiplus::Rect gdip_rect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); if (!painting) { HDC gdi_dc = GetWindowDC(window); Gdiplus::Graphics *pGraphics = new Gdiplus::Graphics(gdi_dc); pGraphics->FillRectangle(&gdip_brush, gdip_rect); delete pGraphics; ReleaseDC(window, gdi_dc); } paintContext->FillRectangle(&gdip_brush, gdip_rect); return Success(); } S::Int S::GUI::SurfaceGDIPlus::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect destRect = rightToLeft.TranslateRect(iDestRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ Gdiplus::Bitmap *gdip_bitmap = (Gdiplus::Bitmap *) bitmap.GetSystemBitmap(); if (!painting) { HDC gdi_dc = GetWindowDC(window); Gdiplus::Graphics *screen = new Gdiplus::Graphics(gdi_dc); screen->SetCompositingMode(Gdiplus::CompositingModeSourceOver); screen->DrawImage(gdip_bitmap, Gdiplus::Rect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()), srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), Gdiplus::UnitPixel, NIL, NIL, NIL); delete screen; ReleaseDC(window, gdi_dc); } paintContext->SetCompositingMode(Gdiplus::CompositingModeSourceOver); paintContext->DrawImage(gdip_bitmap, Gdiplus::Rect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()), srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), Gdiplus::UnitPixel, NIL, NIL, NIL); return Success(); } S::Int S::GUI::SurfaceGDIPlus::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect srcRect = rightToLeft.TranslateRect(iSrcRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ Gdiplus::Bitmap *gdip_bitmap = (Gdiplus::Bitmap *) bitmap.GetSystemBitmap(); Gdiplus::Graphics gdip_graphics(gdip_bitmap); gdip_graphics.DrawImage(paintBitmap, Gdiplus::Rect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()), srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), Gdiplus::UnitPixel, NIL, NIL, NIL); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/000077500000000000000000000000001516402577000240705ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/Makefile000066400000000000000000000007061516402577000255330ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_HAIKU),True) OBJECTS += bitmaphaiku.o fonthaiku.o surfacehaiku.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/bitmaphaiku.cpp000066400000000000000000000116141516402577000270750ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2024 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::GUI::BitmapBackend *CreateBitmapHaiku_pV(S::Void *iBitmap) { return new S::GUI::BitmapHaiku(iBitmap); } S::GUI::BitmapBackend *CreateBitmapHaiku_crSI(const S::GUI::Size &iSize, S::Int iDepth) { return new S::GUI::BitmapHaiku(iSize, iDepth); } S::GUI::BitmapBackend *CreateBitmapHaiku_cI(const int nil) { return new S::GUI::BitmapHaiku(nil); } S::GUI::BitmapBackend *CreateBitmapHaiku_crB(const S::GUI::BitmapBackend &iBitmap) { return new S::GUI::BitmapHaiku((const S::GUI::BitmapHaiku &) iBitmap); } S::Int bitmapHaikuTmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapHaiku_pV); S::Int bitmapHaikuTmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapHaiku_crSI); S::Int bitmapHaikuTmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapHaiku_cI); S::Int bitmapHaikuTmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapHaiku_crB); S::GUI::BitmapHaiku::BitmapHaiku(Void *iBitmap) { type = BITMAP_HAIKU; bitmap = NIL; SetSystemBitmap(iBitmap); } S::GUI::BitmapHaiku::BitmapHaiku(const Size &iSize, Int iDepth) { type = BITMAP_HAIKU; bitmap = NIL; CreateBitmap(iSize, iDepth); } S::GUI::BitmapHaiku::BitmapHaiku(const int nil) { type = BITMAP_HAIKU; bitmap = NIL; SetSystemBitmap(NIL); } S::GUI::BitmapHaiku::BitmapHaiku(const BitmapHaiku &iBitmap) { type = BITMAP_HAIKU; bitmap = NIL; SetSystemBitmap((Void *) iBitmap.bitmap); } S::GUI::BitmapHaiku::~BitmapHaiku() { DeleteBitmap(); } S::Bool S::GUI::BitmapHaiku::CreateBitmap(const Size &nSize, Int nDepth) { DeleteBitmap(); if (nDepth == -1) nDepth = 24; if (nDepth != 24 && nDepth != 32) nDepth = 24; bitmap = new BBitmap(BRect(0, 0, nSize.cx - 1, nSize.cy - 1), nDepth == 32 ? B_RGBA32 : B_RGB32, true); if (bitmap == NIL) return False; bytes = bitmap->Bits(); size = nSize; depth = nDepth; bpp = 32; align = 4; return True; } S::Bool S::GUI::BitmapHaiku::DeleteBitmap() { if (bitmap != NIL) { delete bitmap; bitmap = NIL; size = Size(0, 0); depth = 0; bytes = NIL; bpp = 0; align = 0; } return True; } S::Bool S::GUI::BitmapHaiku::SetSystemBitmap(Void *nBitmap) { if (nBitmap == GetSystemBitmap()) return True; if (nBitmap == NIL) { DeleteBitmap(); } else { BBitmap *haikuBitmap = (BBitmap *) nBitmap; BRect bounds = haikuBitmap->Bounds(); CreateBitmap(Size(bounds.right + 1, bounds.bottom + 1), haikuBitmap->ColorSpace() == B_RGBA32 ? 32 : 24); BView *view = new BView(bounds, NULL, B_FOLLOW_ALL_SIDES, 0); bitmap->AddChild(view); bitmap->Lock(); view->DrawBitmap(haikuBitmap, BPoint(0, 0)); bitmap->Unlock(); bitmap->RemoveChild(view); delete view; } return True; } S::Void *S::GUI::BitmapHaiku::GetSystemBitmap() const { return (Void *) bitmap; } S::Bool S::GUI::BitmapHaiku::SetPixel(const Point &point, const Color &iColor) { if (bytes == NIL) return False; if (point.y >= size.cy || point.x >= size.cx) return False; Color color = iColor.ConvertTo(Color::RGBA); UnsignedByte *data = ((UnsignedByte *) bytes); Int offset = point.y * (size.cx * 4) + point.x * 4; switch (depth) { case 24: data[offset + 0] = (color >> 16) & 255; data[offset + 1] = (color >> 8) & 255; data[offset + 2] = color & 255; return True; case 32: data[offset + 0] = (color >> 16) & 255; data[offset + 1] = (color >> 8) & 255; data[offset + 2] = color & 255; data[offset + 3] = (color >> 24) & 255; return True; } return False; } S::GUI::Color S::GUI::BitmapHaiku::GetPixel(const Point &point) const { if (bytes == NIL) return 0; if (point.y >= size.cy || point.x >= size.cx) return 0; UnsignedByte *data = ((UnsignedByte *) bytes); Int offset = point.y * (size.cx * 4) + point.x * 4; switch (depth) { case 24: return Color( data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGB); case 32: return Color(data[offset + 3] << 24 | data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGBA); } return 0; } S::GUI::BitmapBackend &S::GUI::BitmapHaiku::operator =(const BitmapBackend &newBitmap) { if (&newBitmap == this) return *this; SetSystemBitmap((Void *) ((BitmapHaiku &) newBitmap).bitmap); return *this; } S::Bool S::GUI::BitmapHaiku::operator ==(const int nil) const { if (bitmap == NIL) return True; else return False; } S::Bool S::GUI::BitmapHaiku::operator !=(const int nil) const { if (bitmap == NIL) return False; else return True; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/fonthaiku.cpp000066400000000000000000000037601516402577000265720ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include S::GUI::FontBackend *CreateFontHaiku(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor) { return new S::GUI::FontHaiku(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor); } S::Int fontHaikuTmp = S::GUI::FontBackend::SetBackend(&CreateFontHaiku); S::Int addFontHaikuInitTmp = S::AddInitFunction(&S::GUI::FontHaiku::Initialize); S::Int S::GUI::FontHaiku::Initialize() { font_family family; be_plain_font->GetFamilyAndStyle(&family, NIL); Font::Default = family; Setup::FontSize = be_plain_font->Size() / 96.0 * 72.0 / Font::DefaultSize; return Success(); } S::GUI::FontHaiku::FontHaiku(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor) { type = FONT_HAIKU; } S::GUI::FontHaiku::~FontHaiku() { } S::GUI::Size S::GUI::FontHaiku::GetTextSize(const String &text) const { if (text == NIL) return Size(); Float dpi = Surface().GetSurfaceDPI(); BFont font; font_height height; font.SetFamilyAndStyle(fontName, NULL); font.SetFace((fontStyle & Font::Italic ? B_ITALIC_FACE : 0) | (fontWeight >= Font::Bold ? B_BOLD_FACE : 0)); font.SetSize(Math::Round(fontSize * dpi / 72.0)); font.GetHeight(&height); return Size(font.StringWidth(text.ConvertTo("UTF-8")), Math::Ceil(height.ascent + height.descent)); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/surfacehaiku.cpp000066400000000000000000000337541516402577000272620ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include S::GUI::SurfaceBackend *CreateSurfaceHaiku(S::Void *iSurface, const S::GUI::Size &maxSize) { return new S::GUI::SurfaceHaiku(iSurface, maxSize); } S::Int surfaceHaikuTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceHaiku); S::Short S::GUI::SurfaceHaiku::surfaceDPI = -1; S::GUI::SurfaceHaiku::SurfaceHaiku(Void *iView, const Size &maxSize) { type = SURFACE_HAIKU; view = (BView *) iView; bitmap = NIL; bitmapView = NIL; if (view != NIL) { size = maxSize; BScreen screen; BRect frame = screen.Frame(); if (maxSize == Size()) { size.cx = 1 + frame.right + 2; size.cy = 1 + frame.bottom + 2; } fontSize.SetFontSize(GetSurfaceDPI()); rightToLeft.SetSurfaceSize(size); bitmap = new BBitmap(BRect(0, 0, size.cx, size.cy), screen.ColorSpace(), true); bitmapView = new BView(bitmap->Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0); bitmap->AddChild(bitmapView); paintRects.Add(Rect(Point(0, 0), size)); allocSize = size; } } S::GUI::SurfaceHaiku::~SurfaceHaiku() { if (view != NIL) { bitmap->RemoveChild(bitmapView); delete bitmapView; delete bitmap; } } S::Int S::GUI::SurfaceHaiku::Lock() { SurfaceBackend::Lock(); if (view != NIL && !painting) { BWindow *window = view->Window(); while (window->LockWithTimeout(0) != B_OK) { SurfaceBackend::Release(); Application::Lock::ResumeLock(Application::Lock::SuspendLock()); SurfaceBackend::Lock(); } bitmap->Lock(); } return Success(); } S::Int S::GUI::SurfaceHaiku::Release() { if (view != NIL && !painting) { BWindow *window = view->Window(); bitmap->Unlock(); window->Unlock(); } return SurfaceBackend::Release(); } S::Int S::GUI::SurfaceHaiku::SetSize(const Size &nSize) { size = nSize; rightToLeft.SetSurfaceSize(size); if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success(); if (view != NIL && !painting) { bitmap->Unlock(); bitmap->RemoveChild(bitmapView); delete bitmapView; delete bitmap; paintRects.RemoveAll(); bitmap = new BBitmap(BRect(0, 0, size.cx, size.cy), B_RGB32, true); bitmapView = new BView(bitmap->Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0); bitmap->AddChild(bitmapView); bitmap->Lock(); paintRects.Add(Rect(Point(0, 0), size)); } allocSize = nSize; return Success(); } const S::GUI::Size &S::GUI::SurfaceHaiku::GetSize() const { return size; } S::Int S::GUI::SurfaceHaiku::PaintRect(const Rect &pRect) { if (painting) return Error(); if (view != NIL) { bitmapView->Sync(); view->SetDrawingMode(B_OP_COPY); view->DrawBitmapAsync(bitmap, BRect(pRect.left, pRect.top, pRect.right, pRect.bottom), BRect(pRect.left, pRect.top, pRect.right, pRect.bottom)); } return Success(); } S::Int S::GUI::SurfaceHaiku::StartPaint(const Rect &iPRect) { if (view == NIL) return Success(); Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast()); BRegion clippingRegion(BRect(pRect.left, pRect.top, pRect.right, pRect.bottom)); bitmapView->PushState(); bitmapView->ConstrainClippingRegion(&clippingRegion); paintRects.Add(pRect); painting++; return Success(); } S::Int S::GUI::SurfaceHaiku::EndPaint() { if (!painting) return Error(); painting--; if (painting == 0) PaintRect(paintRects.GetLast()); paintRects.RemoveNth(paintRects.Length() - 1); bitmapView->PopState(); return Success(); } S::Void *S::GUI::SurfaceHaiku::GetSystemSurface() const { return (Void *) view; } S::Short S::GUI::SurfaceHaiku::GetSurfaceDPI() const { if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor()); if (surfaceDPI != -1) return surfaceDPI; Float dpi = 96.0; surfaceDPI = Math::Round(dpi * Setup::FontSize); return surfaceDPI; } S::Int S::GUI::SurfaceHaiku::SetPixel(const Point &iPoint, const Color &color) { if (view == NIL) return Success(); Point point = rightToLeft.TranslatePoint(iPoint); if (!painting) { view->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue()); view->FillRect(BRect(point.x, point.y, point.x, point.y)); } bitmapView->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue()); bitmapView->FillRect(BRect(point.x, point.y, point.x, point.y)); return Success(); } S::Int S::GUI::SurfaceHaiku::Line(const Point &iPos1, const Point &iPos2, const Color &color) { if (view == NIL) return Success(); Point pos1 = rightToLeft.TranslatePoint(iPos1); Point pos2 = rightToLeft.TranslatePoint(iPos2); /* Adjust to Windows GDI behavior for diagonal lines. */ if (Math::Abs(pos2.x - pos1.x) == Math::Abs(pos2.y - pos1.y)) { if (pos1.x < pos2.x) pos2.x--; else if (pos1.x > pos2.x) pos2.x++; if (pos1.y < pos2.y) pos2.y--; else if (pos1.y > pos2.y) pos2.y++; } /* Adjust to Windows GDI behaviour for horizontal and vertical lines. */ if (pos1.x == pos2.x && pos1.y < pos2.y) pos2.y--; if (pos1.x == pos2.x && pos1.y > pos2.y) pos1.y--; if (pos1.y == pos2.y && pos1.x < pos2.x) pos2.x--; if (pos1.y == pos2.y && pos1.x > pos2.x) pos1.x--; if (!painting) { view->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue()); view->MovePenTo(BPoint(pos1.x, pos1.y)); view->StrokeLine(BPoint(pos2.x, pos2.y)); } bitmapView->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue()); bitmapView->MovePenTo(BPoint(pos1.x, pos1.y)); bitmapView->StrokeLine(BPoint(pos2.x, pos2.y)); return Success(); } S::Int S::GUI::SurfaceHaiku::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse) { if (view == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect) - Size(1, 1); if (!painting) view->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue()); bitmapView->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue()); if (style & Rect::Filled) { if (style & Rect::Rounded) { if (!painting) view->FillRoundRect(BRect(rect.left, rect.top, rect.right, rect.bottom), ellipse.cx, ellipse.cy); bitmapView->FillRoundRect(BRect(rect.left, rect.top, rect.right, rect.bottom), ellipse.cx, ellipse.cy); } else { if (!painting) view->FillRect(BRect(rect.left, rect.top, rect.right, rect.bottom)); bitmapView->FillRect(BRect(rect.left, rect.top, rect.right, rect.bottom)); } } else if (style == Rect::Outlined) { if (!painting) view->StrokeRect(BRect(rect.left, rect.top, rect.right, rect.bottom)); bitmapView->StrokeRect(BRect(rect.left, rect.top, rect.right, rect.bottom)); } else if (style & Rect::Inverted) { if (!painting) view->InvertRect(BRect(rect.left, rect.top, rect.right, rect.bottom)); bitmapView->InvertRect(BRect(rect.left, rect.top, rect.right, rect.bottom)); } else if (style & Rect::Dotted) { pattern pattern = {{ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA }}; if (!painting) view->StrokeRect(BRect(rect.left, rect.top, rect.right, rect.bottom), pattern); bitmapView->StrokeRect(BRect(rect.left, rect.top, rect.right, rect.bottom), pattern); } return Success(); } S::Int S::GUI::SurfaceHaiku::SetText(const String &string, const Rect &iRect, const Font &font, Bool shadow) { if (view == NIL) return Success(); if (string == NIL) return Error(); if (shadow) return SurfaceBackend::SetText(string, iRect, font, shadow); Rect rect = iRect; Int lineHeight = 0; /* Set up Haiku font. */ BFont viewFont; font_height height; viewFont.SetFamilyAndStyle(font.GetName(), NULL); viewFont.SetFace((font.GetStyle() & Font::Italic ? B_ITALIC_FACE : 0) | (font.GetStyle() & Font::Underline ? B_UNDERSCORE_FACE : 0) | (font.GetStyle() & Font::StrikeOut ? B_STRIKEOUT_FACE : 0) | (font.GetWeight() >= Font::Bold ? B_BOLD_FACE : 0)); viewFont.SetSize(Math::Round(font.GetSize() * fontSize.TranslateY(96) / 72.0)); Rect tRect = rightToLeft.TranslateRect(rect); BRegion clippingRegion(BRect(tRect.left, tRect.top, tRect.right, tRect.bottom)); if (!painting) { view->PushState(); view->SetFont(&viewFont); view->SetDrawingMode(B_OP_OVER); view->SetHighColor(font.GetColor().GetRed(), font.GetColor().GetGreen(), font.GetColor().GetBlue()); view->ConstrainClippingRegion(&clippingRegion); } bitmapView->PushState(); bitmapView->SetFont(&viewFont); bitmapView->GetFontHeight(&height); bitmapView->SetDrawingMode(B_OP_OVER); bitmapView->SetHighColor(font.GetColor().GetRed(), font.GetColor().GetGreen(), font.GetColor().GetBlue()); bitmapView->ConstrainClippingRegion(&clippingRegion); /* Draw text line by line. */ const Array &lines = string.Explode("\n"); if (lines.Length() > 1) lineHeight = font.GetScaledTextSizeY() + 3; foreach (const String &line, lines) { Rect tRect = rightToLeft.TranslateRect(rect); tRect.left = rightToLeft.GetRightToLeft() ? tRect.right - font.GetScaledTextSizeX(line) : tRect.left; if (!painting) view->DrawString(line.ConvertTo("UTF-8"), BPoint(tRect.left, tRect.top + height.ascent)); bitmapView->DrawString(line.ConvertTo("UTF-8"), BPoint(tRect.left, tRect.top + height.ascent)); rect.top += lineHeight; } if (!painting) view->PopState(); bitmapView->PopState(); return Success(); } S::Int S::GUI::SurfaceHaiku::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style) { if (view == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect) - Size(1, 1); /* Setup colors. */ Color c1 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color2 : color1; Color c2 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color1 : color2; /* Setup graphics objects and draw gradient. */ BGradient *gradient = new BGradientLinear(0, 0, style == OR_HORZ ? rect.GetWidth() : 0, style == OR_VERT ? rect.GetHeight() : 0); gradient->AddColorStop(BGradient::ColorStop(c1.GetRed(), c1.GetGreen(), c1.GetBlue(), 255, 0), 0); gradient->AddColorStop(BGradient::ColorStop(c2.GetRed(), c2.GetGreen(), c2.GetBlue(), 255, 255), 1); if (!painting) view->FillRect(BRect(rect.left, rect.top, rect.right, rect.bottom), *gradient); bitmapView->FillRect(BRect(rect.left, rect.top, rect.right, rect.bottom), *gradient); delete gradient; return Success(); } S::Int S::GUI::SurfaceHaiku::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect) { if (view == NIL) return Success(); if (bitmap == NIL) return Error(); Rect destRect = rightToLeft.TranslateRect(iDestRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ drawing_mode drawingMode = bitmap.GetDepth() == 32 ? B_OP_ALPHA : B_OP_COPY; if (!painting) view->SetDrawingMode(drawingMode); bitmapView->SetDrawingMode(drawingMode); if (destRect.GetSize() == srcRect.GetSize()) { if (!painting) view->DrawBitmap((BBitmap *) bitmap.GetSystemBitmap(), BRect(srcRect.left, srcRect.top, srcRect.right, srcRect.bottom), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR); bitmapView->DrawBitmap((BBitmap *) bitmap.GetSystemBitmap(), BRect(srcRect.left, srcRect.top, srcRect.right, srcRect.bottom), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR); } else { /* Quality of Haiku's biliniear filter is not good enough and there are no other options. * Use our own weighted average scaling until there are better alternatives offered by Haiku. */ Float scaleFactorX = Float(srcRect.GetWidth()) / Float(destRect.GetWidth()); Float scaleFactorY = Float(srcRect.GetHeight()) / Float(destRect.GetHeight()); Size srcSize = bitmap.GetSize(); const Bitmap &scaledBitmap = bitmap.Scale(Size(Float(srcSize.cx) / scaleFactorX, Float(srcSize.cy) / scaleFactorY)); if (!painting) view->DrawBitmap((BBitmap *) scaledBitmap.GetSystemBitmap(), BRect(Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, Float(srcRect.right) / scaleFactorX, Float(srcRect.bottom) / scaleFactorY), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR); bitmapView->DrawBitmap((BBitmap *) scaledBitmap.GetSystemBitmap(), BRect(Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, Float(srcRect.right) / scaleFactorX, Float(srcRect.bottom) / scaleFactorY), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR); } return Success(); } S::Int S::GUI::SurfaceHaiku::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect) { if (view == NIL) return Success(); if (bitmap == NIL) return Error(); Rect srcRect = rightToLeft.TranslateRect(iSrcRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ BBitmap *destBitmap = (BBitmap *) bitmap.GetSystemBitmap(); BView *destView = new BView(destBitmap->Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0); destBitmap->AddChild(destView); destBitmap->Lock(); bitmapView->Sync(); destView->DrawBitmap(this->bitmap, BRect(srcRect.left, srcRect.top, srcRect.right, srcRect.bottom), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR); destBitmap->Unlock(); destBitmap->RemoveChild(destView); delete destView; return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/surfacebackend.cpp000077500000000000000000000216731516402577000264470ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::GUI::SurfaceBackend *CreateSurfaceBackend(S::Void *iSurface, const S::GUI::Size &maxSize) { return new S::GUI::SurfaceBackend(iSurface, maxSize); } S::GUI::SurfaceBackend *(*S::GUI::SurfaceBackend::backend_creator)(S::Void *, const S::GUI::Size &) = &CreateSurfaceBackend; S::Int S::GUI::SurfaceBackend::SetBackend(SurfaceBackend *(*backend)(Void *, const Size &)) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::GUI::SurfaceBackend *S::GUI::SurfaceBackend::CreateBackendInstance(Void *iSurface, const Size &maxSize) { return backend_creator(iSurface, maxSize); } S::GUI::SurfaceBackend::SurfaceBackend(Void *iSurface, const Size &maxSize) { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) SurfaceGDI(); #endif type = SURFACE_NONE; size.cx = 0; size.cy = 0; paintRect.left = -1; paintRect.top = -1; paintRect.right = -1; paintRect.bottom = -1; painting = 0; } S::GUI::SurfaceBackend::~SurfaceBackend() { } S::Int S::GUI::SurfaceBackend::Lock() { return Application::Lock::Acquire(); } S::Int S::GUI::SurfaceBackend::Release() { return Application::Lock::Release(); } S::Short S::GUI::SurfaceBackend::GetSurfaceType() const { return type; } S::Int S::GUI::SurfaceBackend::SetSize(const Size &nSize) { size = nSize; rightToLeft.SetSurfaceSize(size); return Success(); } const S::GUI::Size &S::GUI::SurfaceBackend::GetSize() const { return size; } S::Int S::GUI::SurfaceBackend::SetRightToLeft(Bool nRightToLeft) { rightToLeft.SetRightToLeft(nRightToLeft); return Success(); } S::Int S::GUI::SurfaceBackend::PaintRect(const Rect &pRect) { return Success(); } S::Int S::GUI::SurfaceBackend::StartPaint(const Rect &pRect) { painting++; return Success(); } S::Int S::GUI::SurfaceBackend::EndPaint() { painting--; return Success(); } S::Void *S::GUI::SurfaceBackend::GetSystemSurface() const { return NIL; } S::Short S::GUI::SurfaceBackend::GetSurfaceDPI() const { return 96; } S::Int S::GUI::SurfaceBackend::SetPixel(const Point &point, const Color &color) { return Success(); } S::Int S::GUI::SurfaceBackend::Line(const Point &pos1, const Point &pos2, const Color &color) { return Success(); } S::Int S::GUI::SurfaceBackend::Frame(const Rect &iRect, Short style) { Rect rect = rightToLeft.TranslateRect(iRect); Point p1 = Point(rect.left, rect.top); Point p2 = Point(rect.right - 1, rect.top); Point p3 = Point(rect.left, rect.bottom - 1); Point p4 = Point(rect.right - 1, rect.bottom - 1); Long color1 = 0; Long color2 = 0; switch (style) { case FRAME_UP: color1 = Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255)); color2 = Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0)); break; case FRAME_DOWN: color1 = Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0)); color2 = Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255)); break; } Bool preRTL = rightToLeft.GetRightToLeft(); rightToLeft.SetRightToLeft(False); StartPaint(rect); Line(p1, p2, color1); Line(p1, p3, color1); Line(p2, p4, color2); Line(p3, p4, color2); SetPixel(p4, color2); EndPaint(); rightToLeft.SetRightToLeft(preRTL); return Success(); } S::Int S::GUI::SurfaceBackend::Box(const Rect &rect, const Color &color, Int style, const Size &ellipse) { return Success(); } S::Int S::GUI::SurfaceBackend::SetText(const String &string, const Rect &iRect, const Font &iFont, Bool shadow) { if (shadow) { Rect rect = iRect + Point(2, 2); Font font = iFont; Int fontColor = font.GetColor(); font.SetColor(Color((Int) ((Float) Setup::BackgroundColor.GetRed() / 3 * 2), (Int) ((Float) Setup::BackgroundColor.GetGreen() / 3 * 2), (Int) ((Float) Setup::BackgroundColor.GetBlue() / 3 * 2))); SetText(string, rect, font, False); rect = rect - Point(2, 2); font.SetColor(fontColor); SetText(string, rect, font, False); } return Success(); } S::Int S::GUI::SurfaceBackend::Gradient(const Rect &rect, const Color &color1, const Color &color2, Int style) { Float red1 = color1.GetRed(); Float green1 = color1.GetGreen(); Float blue1 = color1.GetBlue(); Float red2 = color2.GetRed(); Float green2 = color2.GetGreen(); Float blue2 = color2.GetBlue(); Int xmax = rect.GetWidth(); Int ymax = rect.GetHeight(); Bitmap bmp(Size(xmax, ymax)); switch (style) { case OR_HORZ: { Float biasr = (red2 - red1) / xmax; Float biasg = (green2 - green1) / xmax; Float biasb = (blue2 - blue1) / xmax; if (rightToLeft.GetRightToLeft()) { for (Int x = xmax - 1; x >= 0; x--) { red1 = red1 + biasr; green1 = green1 + biasg; blue1 = blue1 + biasb; for (Int y = 0; y < ymax; y++) bmp.SetPixel(Point(x, y), Color((Int) red1, (Int) green1, (Int) blue1)); } } else { for (Int x = 0; x < xmax; x++) { red1 = red1 + biasr; green1 = green1 + biasg; blue1 = blue1 + biasb; for (Int y = 0; y < ymax; y++) bmp.SetPixel(Point(x, y), Color((Int) red1, (Int) green1, (Int) blue1)); } } } break; case OR_VERT: { Float biasr = (red2 - red1) / ymax; Float biasg = (green2 - green1) / ymax; Float biasb = (blue2 - blue1) / ymax; for (Int y = 0; y < ymax; y++) { red1 = red1 + biasr; green1 = green1 + biasg; blue1 = blue1 + biasb; for (Int x = 0; x < xmax; x++) bmp.SetPixel(Point(x, y), Color((Int) red1, (Int) green1, (Int) blue1)); } } break; } BlitFromBitmap(bmp, Rect(Point(0, 0), rect.GetSize()), rect); return Success(); } S::Int S::GUI::SurfaceBackend::Bar(const Point &iP1, const Point &iP2, Int orientation) { Point p1 = rightToLeft.TranslatePoint(iP1); Point p2 = rightToLeft.TranslatePoint(iP2); if (rightToLeft.GetRightToLeft()) { if (orientation == OR_HORZ) { p1 = rightToLeft.TranslatePoint(iP2); p2 = rightToLeft.TranslatePoint(iP1); } if (orientation == OR_VERT) { p1 -= Point(2, 0); p2 -= Point(2, 0); } } Bool preRTL = rightToLeft.GetRightToLeft(); rightToLeft.SetRightToLeft(False); if (orientation == OR_HORZ) { Line(p1, p2, Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0))); p1.y++; p2.y++; Line(p1, p2, Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255))); } else if (orientation == OR_VERT) { p2.y++; Line(p1, p2, Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0))); p1.x++; p2.x++; Line(p1, p2, Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255))); } rightToLeft.SetRightToLeft(preRTL); return Success(); } S::Int S::GUI::SurfaceBackend::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &destRect) { return Success(); } S::Int S::GUI::SurfaceBackend::BlitToBitmap(const Rect &srcRect, Bitmap &bitmap, const Rect &destRect) { return Success(); } S::Int S::GUI::SurfaceBackend::PremultiplyAlpha(Bitmap &bitmap) { if (bitmap.GetDepth() != 32) return Success(); Point point; Size size = bitmap.GetSize(); for (point.y = 0; point.y < size.cy; point.y++) { for (point.x = 0; point.x < size.cx; point.x++) { Color pixel = bitmap.GetPixel(point); if (pixel.GetAlpha() != 255) bitmap.SetPixel(point, Color( pixel.GetRed() * pixel.GetAlpha() / 255 | (pixel.GetGreen() * pixel.GetAlpha() / 255) << 8 | (pixel.GetBlue() * pixel.GetAlpha() / 255) << 16 | pixel.GetAlpha() << 24, Color::RGBA)); } } return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/000077500000000000000000000000001516402577000237255ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/Makefile000066400000000000000000000015771516402577000253770ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags x11) ifneq ($(BUILD_CAIRO),True) MYCCOPTS += $(shell pkg-config --cflags xft) endif endif endif endif ifeq ($(USE_BUNDLED_LIBFRIBIDI),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support -DFRIBIDI_LIB_STATIC endif # Enter object files here: OBJECTS = ifeq ($(BUILD_XLIB),True) OBJECTS += bitmapxlib.o ifneq ($(BUILD_CAIRO),True) OBJECTS += fontxlib.o surfacexlib.o endif endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/bitmapxlib.cpp000077500000000000000000000131261516402577000265720ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include using namespace X11; S::GUI::BitmapBackend *CreateBitmapXLib_pV(S::Void *iBitmap) { return new S::GUI::BitmapXLib(iBitmap); } S::GUI::BitmapBackend *CreateBitmapXLib_crSI(const S::GUI::Size &iSize, S::Int iDepth) { return new S::GUI::BitmapXLib(iSize, iDepth); } S::GUI::BitmapBackend *CreateBitmapXLib_cI(const int nil) { return new S::GUI::BitmapXLib(nil); } S::GUI::BitmapBackend *CreateBitmapXLib_crB(const S::GUI::BitmapBackend &iBitmap) { return new S::GUI::BitmapXLib((const S::GUI::BitmapXLib &) iBitmap); } S::Int bitmapXLibTmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapXLib_pV); S::Int bitmapXLibTmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapXLib_crSI); S::Int bitmapXLibTmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapXLib_cI); S::Int bitmapXLibTmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapXLib_crB); S::GUI::BitmapXLib::BitmapXLib(Void *iBitmap) { Initialize(); SetSystemBitmap(iBitmap); } S::GUI::BitmapXLib::BitmapXLib(const Size &iSize, Int iDepth) { Initialize(); CreateBitmap(iSize, iDepth); } S::GUI::BitmapXLib::BitmapXLib(const int nil) { Initialize(); SetSystemBitmap(NIL); } S::GUI::BitmapXLib::BitmapXLib(const BitmapXLib &iBitmap) { Initialize(); SetSystemBitmap((Void *) iBitmap.bitmap); } S::GUI::BitmapXLib::~BitmapXLib() { DeleteBitmap(); } S::Void S::GUI::BitmapXLib::Initialize() { type = BITMAP_XLIB; bitmap = NIL; display = Backends::BackendXLib::GetDisplay(); } S::Bool S::GUI::BitmapXLib::CreateBitmap(const Size &nSize, Int nDepth) { if (display == NIL) return False; DeleteBitmap(); if (nDepth == -1) nDepth = XDefaultDepth(display, XDefaultScreen(display)); if (nDepth != 24 && nDepth != 32) nDepth = 24; /* Find best fit for pixel format. */ int count = 0; int index = 0; XPixmapFormatValues *formats = XListPixmapFormats(display, &count); for (Int i = 0; i < count; i++) { if (Math::Abs(formats[i].depth - nDepth) < Math::Abs(formats[index].depth - nDepth)) index = i; if (formats[i].depth == nDepth) break; } /* Allocate and create image. */ bytes = new UnsignedByte [nSize.cy * nSize.cx * (formats[index].bits_per_pixel / 8) + nSize.cy * (((nSize.cx * formats[index].bits_per_pixel) % formats[index].scanline_pad) / 8)]; bitmap = XCreateImage(display, XDefaultVisual(display, XDefaultScreen(display)), formats[index].depth, ZPixmap, 0, (char *) bytes, nSize.cx, nSize.cy, formats[index].scanline_pad, 0); if (bitmap == NIL) { delete [] (UnsignedByte *) bytes; XFree(formats); return False; } size = nSize; depth = formats[index].depth; bpp = formats[index].bits_per_pixel; align = formats[index].scanline_pad / 8; XFree(formats); return True; } S::Bool S::GUI::BitmapXLib::DeleteBitmap() { if (bitmap != NIL) { delete [] bitmap->data; bitmap->data = NIL; XDestroyImage(bitmap); bitmap = NIL; size = Size(0, 0); depth = 0; bytes = NIL; bpp = 0; align = 0; } return True; } S::Bool S::GUI::BitmapXLib::SetSystemBitmap(Void *nBitmap) { if (nBitmap == GetSystemBitmap()) return True; if (nBitmap == NIL) { DeleteBitmap(); } else { XImage *image = (XImage *) nBitmap; CreateBitmap(Size(image->width, image->height), image->depth); memcpy(bitmap->data, image->data, size_t(image->height) * size_t(image->bytes_per_line)); } return True; } S::Void *S::GUI::BitmapXLib::GetSystemBitmap() const { return (Void *) bitmap; } S::Bool S::GUI::BitmapXLib::SetPixel(const Point &iPoint, const Color &iColor) { if (bitmap == NIL) return Error(); Color color = iColor.ConvertTo(Color::RGBA); if (depth == 16) XPutPixel(bitmap, iPoint.x, iPoint.y, ((color.GetRed() >> 3) << 11) | ((color.GetGreen() >> 2) << 5) | (color.GetBlue() >> 3)); else if (depth == 24) XPutPixel(bitmap, iPoint.x, iPoint.y, ( color.GetRed() << 16) | ( color.GetGreen() << 8) | (color.GetBlue() )); else if (depth == 32) XPutPixel(bitmap, iPoint.x, iPoint.y, (color.GetAlpha() << 24) | ( color.GetRed() << 16) | ( color.GetGreen() << 8) | (color.GetBlue() )); return True; } S::GUI::Color S::GUI::BitmapXLib::GetPixel(const Point &iPoint) const { if (bitmap == NIL) return Color(); Long value = XGetPixel(bitmap, iPoint.x, iPoint.y); if (depth == 16) return Color(((value >> 11) & 31) << 3, ((value >> 5) & 63) << 2, (value & 31) << 3, Color::RGB); else if (depth == 24) return Color( (value >> 16) & 255, (value >> 8) & 255, value & 255 , Color::RGB); else if (depth == 32) return ((value >> 24) & 255) << 24 | Color( (value >> 16) & 255, (value >> 8) & 255, value & 255 , Color::RGBA); return Color(); } S::GUI::BitmapBackend &S::GUI::BitmapXLib::operator =(const BitmapBackend &newBitmap) { if (&newBitmap == this) return *this; SetSystemBitmap((Void *) ((BitmapXLib &) newBitmap).bitmap); return *this; } S::Bool S::GUI::BitmapXLib::operator ==(const int nil) const { if (bitmap == NIL) return True; else return False; } S::Bool S::GUI::BitmapXLib::operator !=(const int nil) const { if (bitmap == NIL) return False; else return True; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/fontxlib.cpp000066400000000000000000000066331516402577000262660ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include using namespace X11; #include S::GUI::FontBackend *CreateFontXLib(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor) { return new S::GUI::FontXLib(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor); } S::Int fontXLibTmp = S::GUI::FontBackend::SetBackend(&CreateFontXLib); S::Int addFontXLibInitTmp = S::AddInitFunction(&S::GUI::FontXLib::Initialize); S::Int S::GUI::FontXLib::Initialize() { Font::Default = "Helvetica"; Setup::FontSize = 1.0; String font = Backends::BackendXLib::QueryGSettings("org.gnome.desktop.interface", "font-name"); Float scaleFactor = Backends::BackendXLib::QueryGSettings("org.gnome.desktop.interface", "text-scaling-factor").ToFloat(); if (font != NIL) { Font::Default = font.SubString(1, font.FindLast(" ") - 1); Setup::FontSize = font.SubString(font.FindLast(" ") + 1, font.Length() - font.FindLast(" ") - 2).ToFloat() / Font::DefaultSize; } if (scaleFactor != 0) Setup::FontSize *= scaleFactor; return Success(); } S::GUI::FontXLib::FontXLib(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor) { type = FONT_XLIB; } S::GUI::FontXLib::~FontXLib() { } S::GUI::Size S::GUI::FontXLib::GetTextSize(const String &iText) const { if (iText == NIL) return Size(); Display *display = Backends::BackendXLib::GetDisplay(); if (display == NIL) return Size(); String text = iText; Int textLength = text.Length(); Float dpi = Surface().GetSurfaceDPI(); Bool rtlCharacters = False; for (Int i = 0; i < textLength; i++) if (text[i] >= 0x0590 && text[i] <= 0x08FF) { rtlCharacters = True; break; } if (rtlCharacters && Setup::useIconv) { /* Reorder the string with fribidi. */ FriBidiChar *visual = new FriBidiChar [textLength + 1]; FriBidiParType type = FRIBIDI_PAR_RTL; fribidi_log2vis((FriBidiChar *) text.ConvertTo("UCS-4LE"), textLength, &type, visual, NIL, NIL, NIL); visual[textLength] = 0; text.ImportFrom("UCS-4LE", (char *) visual); delete [] visual; } /* Get text extents. */ XftFont *font = XftFontOpenName(display, XDefaultScreen(display), String(fontName).Append("-").Append(String::FromInt(Math::Round(fontSize * dpi / 96.0))).Append(":").Append(fontWeight >= Font::Bold ? "bold" : "medium").Append(fontStyle & Font::Italic ? ":italic" : "")); XGlyphInfo extents = { 0 }; XftTextExtents16(display, font, (XftChar16 *) text.ConvertTo("UCS2"), textLength, &extents); XftFontClose(display, font); int lines = 1; for (Int i = 0; i < textLength; i++) if (text[i] == '\n') lines++; return Size(extents.width - 2, (font->ascent + 2) * lines); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/surfacexlib.cpp000077500000000000000000000404231516402577000267460ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace X11; S::GUI::SurfaceBackend *CreateSurfaceXLib(S::Void *iSurface, const S::GUI::Size &) { return new S::GUI::SurfaceXLib(iSurface); } S::Int surfaceXLibTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceXLib); S::Short S::GUI::SurfaceXLib::surfaceDPI = -1; S::GUI::SurfaceXLib::SurfaceXLib(Void *iWindow, const Size &maxSize) { type = SURFACE_XLIB; window = (X11::Window) iWindow; bitmap = NIL; gc = NIL; display = Backends::BackendXLib::GetDisplay(); if (window != NIL) { size = maxSize; if (maxSize == Size()) { size.cx = XDisplayWidth(display, XDefaultScreen(display)) + 2; size.cy = XDisplayHeight(display, XDefaultScreen(display)) + 2; } fontSize.SetFontSize(GetSurfaceDPI()); rightToLeft.SetSurfaceSize(size); XWindowAttributes windowAttributes; XGetWindowAttributes(display, window, &windowAttributes); bitmap = XCreatePixmap(display, window, size.cx, size.cy, windowAttributes.depth); gc = XCreateGC(display, bitmap, 0, NIL); paintRects.Add(Rect(Point(0, 0), size)); allocSize = size; } } S::GUI::SurfaceXLib::~SurfaceXLib() { if (bitmap != NIL) { XFreeGC(display, gc); XFreePixmap(display, bitmap); } } S::Int S::GUI::SurfaceXLib::SetSize(const Size &nSize) { size = nSize; rightToLeft.SetSurfaceSize(size); if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success(); if (window != NIL && !painting) { XFreeGC(display, gc); XFreePixmap(display, bitmap); paintRects.RemoveAll(); XWindowAttributes windowAttributes; XGetWindowAttributes(display, window, &windowAttributes); bitmap = XCreatePixmap(display, DefaultRootWindow(display), size.cx, size.cy, windowAttributes.depth); gc = XCreateGC(display, bitmap, 0, NIL); paintRects.Add(Rect(Point(0, 0), size)); } allocSize = nSize; return Success(); } const S::GUI::Size &S::GUI::SurfaceXLib::GetSize() const { return size; } S::Int S::GUI::SurfaceXLib::PaintRect(const Rect &pRect) { if (painting) return Error(); if (window != NIL) { XCopyArea(display, bitmap, window, gc, pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight(), pRect.left, pRect.top); } return Success(); } S::Int S::GUI::SurfaceXLib::StartPaint(const Rect &iPRect) { if (window == NIL) return Success(); Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast()); XRectangle clipRect; clipRect.x = pRect.left; clipRect.y = pRect.top; clipRect.width = pRect.GetWidth(); clipRect.height = pRect.GetHeight(); XSetClipRectangles(display, gc, 0, 0, &clipRect, 1, Unsorted); paintRects.Add(pRect); painting++; return Success(); } S::Int S::GUI::SurfaceXLib::EndPaint() { if (!painting) return Error(); painting--; if (painting == 0) { PaintRect(paintRects.GetLast()); XSetClipMask(display, gc, None); } else { const Rect &paintRect = paintRects.GetNth(paintRects.Length() - 2); XRectangle clipRect; clipRect.x = paintRect.left; clipRect.y = paintRect.top; clipRect.width = paintRect.GetWidth(); clipRect.height = paintRect.GetHeight(); XSetClipRectangles(display, gc, 0, 0, &clipRect, 1, Unsorted); } paintRects.RemoveNth(paintRects.Length() - 1); return Success(); } S::Void *S::GUI::SurfaceXLib::GetSystemSurface() const { return (Void *) window; } S::Short S::GUI::SurfaceXLib::GetSurfaceDPI() const { if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor()); if (surfaceDPI != -1) return surfaceDPI; /* Evaluate GDK_SCALE setting. */ Float dpi = 96.0; Int scale = (Int64) Number::FromIntString(getenv("GDK_SCALE")); if (scale > 0) dpi *= scale; surfaceDPI = Math::Round(dpi * Setup::FontSize); return surfaceDPI; } S::Int S::GUI::SurfaceXLib::SetPixel(const Point &iPoint, const Color &color) { if (window == NIL) return Success(); Point point = rightToLeft.TranslatePoint(iPoint); XGCValues gcValues; gcValues.foreground = Color(color.GetBlue(), color.GetGreen(), color.GetRed()); XChangeGC(display, gc, GCForeground, &gcValues); if (!painting) XDrawPoint(display, window, gc, point.x, point.y); XDrawPoint(display, bitmap, gc, point.x, point.y); return Success(); } S::Int S::GUI::SurfaceXLib::Line(const Point &iPos1, const Point &iPos2, const Color &color) { if (window == NIL) return Success(); Point pos1 = rightToLeft.TranslatePoint(iPos1); Point pos2 = rightToLeft.TranslatePoint(iPos2); /* Adjust to Windows GDI behavior for diagonal lines. */ if (Math::Abs(pos2.x - pos1.x) == Math::Abs(pos2.y - pos1.y)) { if (pos1.x < pos2.x) pos2.x--; else if (pos1.x > pos2.x) pos2.x++; if (pos1.y < pos2.y) pos2.y--; else if (pos1.y > pos2.y) pos2.y++; } /* Adjust to Windows GDI behaviour for horizontal and vertical lines. */ if (pos1.x == pos2.x && pos1.y < pos2.y) pos2.y--; if (pos1.x == pos2.x && pos1.y > pos2.y) pos1.y--; if (pos1.y == pos2.y && pos1.x < pos2.x) pos2.x--; if (pos1.y == pos2.y && pos1.x > pos2.x) pos1.x--; XGCValues gcValues; gcValues.foreground = Color(color.GetBlue(), color.GetGreen(), color.GetRed()); XChangeGC(display, gc, GCForeground, &gcValues); if (!painting) XDrawLine(display, window, gc, pos1.x, pos1.y, pos2.x, pos2.y); XDrawLine(display, bitmap, gc, pos1.x, pos1.y, pos2.x, pos2.y); return Success(); } S::Int S::GUI::SurfaceXLib::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse) { if (window == NIL) return Success(); Rect rect = rightToLeft.TranslateRect(iRect); XGCValues gcValues; gcValues.foreground = Color(color.GetBlue(), color.GetGreen(), color.GetRed()); XChangeGC(display, gc, GCForeground, &gcValues); if (style & Rect::Filled) { if (style & Rect::Rounded) { /* ToDo: Allow drawing of rounded rects. */ } else { if (!painting) XFillRectangle(display, window, gc, rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); XFillRectangle(display, bitmap, gc, rect.left, rect.top, rect.GetWidth(), rect.GetHeight()); } } else if (style == Rect::Outlined) { if (!painting) XDrawRectangle(display, window, gc, rect.left, rect.top, rect.GetWidth() - 1, rect.GetHeight() - 1); XDrawRectangle(display, bitmap, gc, rect.left, rect.top, rect.GetWidth() - 1, rect.GetHeight() - 1); } else if (style & Rect::Inverted) { Bitmap area(rect.GetSize()); BlitToBitmap(iRect, area, Rect(Point(0, 0), area.GetSize())); area.InvertColors(); BlitFromBitmap(area, Rect(Point(0, 0), area.GetSize()), iRect); } else if (style & Rect::Dotted) { if (!painting) { for (Int x = rect.left + 1; x < rect.right; x += 2) XDrawPoint(display, window, gc, x, rect.top); for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) XDrawPoint(display, window, gc, rect.right - 1, y); for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) XDrawPoint(display, window, gc, x, rect.bottom - 1); for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) XDrawPoint(display, window, gc, rect.left, y); } for (Int x = rect.left + 1; x < rect.right; x += 2) XDrawPoint(display, bitmap, gc, x, rect.top); for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) XDrawPoint(display, bitmap, gc, rect.right - 1, y); for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) XDrawPoint(display, bitmap, gc, x, rect.bottom - 1); for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) XDrawPoint(display, bitmap, gc, rect.left, y); } return Success(); } S::Int S::GUI::SurfaceXLib::SetText(const String &string, const Rect &iRect, const Font &font, Bool shadow) { if (window == NIL) return Success(); if (string == NIL) return Error(); if (shadow) return SurfaceBackend::SetText(string, iRect, font, shadow); Rect rect = iRect; Int lineHeight = font.GetScaledTextSizeY() + 3; XftFont *xfont = XftFontOpenName(display, XDefaultScreen(display), String(font.GetName()).Append("-").Append(String::FromInt(Math::Round(font.GetSize() * fontSize.TranslateY(96) / 96.0))).Append(":").Append(font.GetWeight() >= Font::Bold ? "bold" : "medium").Append(font.GetStyle() & Font::Italic ? ":italic" : "")); XftDraw *wdraw = XftDrawCreate(display, window, XDefaultVisual(display, XDefaultScreen(display)), XDefaultColormap(display, XDefaultScreen(display))); XftDraw *bdraw = XftDrawCreate(display, bitmap, XDefaultVisual(display, XDefaultScreen(display)), XDefaultColormap(display, XDefaultScreen(display))); /* Allocate text color. */ XRenderColor xrcolor; XftColor xftcolor; xrcolor.red = font.GetColor().GetRed() * 256; xrcolor.green = font.GetColor().GetGreen() * 256; xrcolor.blue = font.GetColor().GetBlue() * 256; xrcolor.alpha = 0xffff; XftColorAllocValue(display, DefaultVisual(display, DefaultScreen(display)), DefaultColormap(display, DefaultScreen(display)), &xrcolor, &xftcolor); /* Set clipping area. */ const Rect &pRect = paintRects.GetLast(); XRectangle clipRect; clipRect.x = pRect.left; clipRect.y = pRect.top; clipRect.width = pRect.GetWidth(); clipRect.height = pRect.GetHeight(); XftDrawSetClipRectangles(wdraw, 0, 0, &clipRect, 1); XftDrawSetClipRectangles(bdraw, 0, 0, &clipRect, 1); /* Draw text line by line. */ const Array &lines = string.Explode("\n"); foreach (String line, lines) { Int lineLength = line.Length(); /* Check for right to left characters in text. */ Bool rtlCharacters = False; for (Int i = 0; i < lineLength; i++) if (line[i] >= 0x0590 && line[i] <= 0x08FF) { rtlCharacters = True; break; } /* Draw text, reordering if necessary. */ Rect tRect = rightToLeft.TranslateRect(rect); if (rtlCharacters && Setup::useIconv) { /* Reorder the string with fribidi. */ FriBidiChar *visual = new FriBidiChar [lineLength + 1]; FriBidiParType type = (rightToLeft.GetRightToLeft() ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR); fribidi_log2vis((FriBidiChar *) line.ConvertTo("UCS-4LE"), lineLength, &type, visual, NIL, NIL, NIL); visual[lineLength] = 0; line.ImportFrom("UCS-4LE", (char *) visual); delete [] visual; } if (!painting) XftDrawString16(wdraw, &xftcolor, xfont, tRect.left, tRect.top + lineHeight - 4, (XftChar16 *) line.ConvertTo("UCS2"), lineLength); XftDrawString16(bdraw, &xftcolor, xfont, tRect.left, tRect.top + lineHeight - 4, (XftChar16 *) line.ConvertTo("UCS2"), lineLength); rect.top += lineHeight; } /* Clean up everything. */ XftColorFree(display, DefaultVisual(display, DefaultScreen(display)), DefaultColormap(display, DefaultScreen(display)), &xftcolor); XftDrawDestroy(wdraw); XftDrawDestroy(bdraw); XftFontClose(display, xfont); return Success(); } S::Int S::GUI::SurfaceXLib::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect destRect = rightToLeft.TranslateRect(iDestRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Convert format if depths do not match. */ XWindowAttributes windowAttributes; XGetWindowAttributes(display, window, &windowAttributes); Float scaleFactorX = Float(srcRect.GetWidth()) / Float(destRect.GetWidth()); Float scaleFactorY = Float(srcRect.GetHeight()) / Float(destRect.GetHeight()); const Bitmap *srcBitmap = &bitmap; Size srcSize = bitmap.GetSize(); Size destSize = Size(Float(srcSize.cx) / scaleFactorX, Float(srcSize.cy) / scaleFactorY); if (bitmap.GetDepth() == 32 || bitmap.GetDepth() != windowAttributes.depth) { const Bitmap &bitmap = srcBitmap->Scale(destSize); Bitmap *copy = new Bitmap(destSize, windowAttributes.depth); XImage *bkgr = XGetImage(display, this->bitmap, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), AllPlanes, ZPixmap); Point point; for (point.y = 0; point.y < destSize.cy; point.y++) { for (point.x = 0; point.x < destSize.cx; point.x++) { Color color = bitmap.GetPixel(point); Int alpha = color.GetAlpha(); if (alpha != 255) { Long background = XGetPixel(bkgr, point.x, point.y); color = ((color.GetRed() * alpha + ((background >> 16) & 255) * (255 - alpha)) / 255) | ((color.GetGreen() * alpha + ((background >> 8) & 255) * (255 - alpha)) / 255) << 8 | ((color.GetBlue() * alpha + ( background & 255) * (255 - alpha)) / 255) << 16; } copy->SetPixel(point, color); } } XDestroyImage(bkgr); srcBitmap = copy; } /* Copy the image. */ if (destRect.GetSize() == srcRect.GetSize()) { if (!painting) XPutImage(display, window, gc, (XImage *) srcBitmap->GetSystemBitmap(), srcRect.left, srcRect.top, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()); XPutImage(display, this->bitmap, gc, (XImage *) srcBitmap->GetSystemBitmap(), srcRect.left, srcRect.top, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()); } else { const Bitmap &bitmap = srcBitmap->Scale(destSize); if (!painting) XPutImage(display, window, gc, (XImage *) bitmap.GetSystemBitmap(), Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()); XPutImage(display, this->bitmap, gc, (XImage *) bitmap.GetSystemBitmap(), Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()); } /* Delete copy if we created one earlier. */ if (bitmap.GetDepth() != windowAttributes.depth) delete srcBitmap; return Success(); } S::Int S::GUI::SurfaceXLib::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect) { if (window == NIL) return Success(); if (bitmap == NIL) return Error(); Rect srcRect = rightToLeft.TranslateRect(iSrcRect); if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 || destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success(); /* Copy the image. */ XImage *image = XGetImage(display, this->bitmap, srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), AllPlanes, ZPixmap); Point point; Float scaleFactorX = Float(srcRect.GetWidth()) / Float(destRect.GetWidth()); Float scaleFactorY = Float(srcRect.GetHeight()) / Float(destRect.GetHeight()); for (point.y = 0; point.y < destRect.GetHeight(); point.y++) { for (point.x = 0; point.x < destRect.GetWidth(); point.x++) { Float red = 0, green = 0, blue = 0; for (Int srcX = Math::Floor(Float(point.x) * scaleFactorX); srcX < Math::Ceil(Float(point.x + 1) * scaleFactorX); srcX++) { for (Int srcY = Math::Floor(Float(point.y) * scaleFactorY); srcY < Math::Ceil(Float(point.y + 1) * scaleFactorY); srcY++) { Long value = XGetPixel(image, srcX, srcY); Float weightX = (1.0 - Math::Max(0.0, Float(point.x) * scaleFactorX - Float(srcX)) - Math::Max(0.0, Float(srcX + 1) - Float(point.x + 1) * scaleFactorX)) / scaleFactorX; Float weightY = (1.0 - Math::Max(0.0, Float(point.y) * scaleFactorY - Float(srcY)) - Math::Max(0.0, Float(srcY + 1) - Float(point.y + 1) * scaleFactorY)) / scaleFactorY; red += Float((value >> 16) & 255) * weightX * weightY; green += Float((value >> 8) & 255) * weightX * weightY; blue += Float( value & 255) * weightX * weightY; } } bitmap.SetPixel(point, Color(red, green, blue)); } } XDestroyImage(image); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/bitmap.cpp000066400000000000000000000105241516402577000231770ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::GUI::Bitmap::Bitmap(const int nil) { backend = BitmapBackend::CreateBackendInstance(nil); } S::GUI::Bitmap::Bitmap(const Size &iSize, Int iDepth) { backend = BitmapBackend::CreateBackendInstance(iSize, iDepth); } S::GUI::Bitmap::Bitmap(const Bitmap &iBitmap) { backend = BitmapBackend::CreateBackendInstance(*(iBitmap.backend)); } S::GUI::Bitmap::Bitmap(Void *iBitmap) { backend = BitmapBackend::CreateBackendInstance(iBitmap); } S::GUI::Bitmap::~Bitmap() { delete backend; } S::Short S::GUI::Bitmap::GetBitmapType() const { return backend->GetBitmapType(); } const S::GUI::Size &S::GUI::Bitmap::GetSize() const { return backend->GetSize(); } S::Byte S::GUI::Bitmap::GetDepth() const { return backend->GetDepth(); } S::UnsignedByte *S::GUI::Bitmap::GetBytes() const { return backend->GetBytes(); } S::Byte S::GUI::Bitmap::GetBitsPerPixel() const { return backend->GetBitsPerPixel(); } S::Byte S::GUI::Bitmap::GetLineAlignment() const { return backend->GetLineAlignment(); } S::Bool S::GUI::Bitmap::CreateBitmap(const Size &nSize, Int nDepth) { return backend->CreateBitmap(nSize, nDepth); } S::Bool S::GUI::Bitmap::DeleteBitmap() { return backend->DeleteBitmap(); } S::Bool S::GUI::Bitmap::SetSystemBitmap(Void *nBitmap) { return backend->SetSystemBitmap(nBitmap); } S::Void *S::GUI::Bitmap::GetSystemBitmap() const { return backend->GetSystemBitmap(); } S::Int S::GUI::Bitmap::GrayscaleBitmap() { return backend->GrayscaleBitmap(); } S::Int S::GUI::Bitmap::InvertColors() { return backend->InvertColors(); } S::Int S::GUI::Bitmap::ReplaceColor(const Color &color1, const Color &color2) { return backend->ReplaceColor(color1, color2); } S::Int S::GUI::Bitmap::SetBackgroundColor(const Color &color) { return backend->SetBackgroundColor(color); } S::GUI::Bitmap S::GUI::Bitmap::Scale(const Size &newSize) const { if (GetSize() == Size() || GetSize() == newSize) return *this; return backend->Scale(newSize); } S::Int S::GUI::Bitmap::BlitFromSurface(Surface *surface, const Rect &srcRect, const Rect &destRect) { if (surface == NIL) return Error(); return surface->BlitToBitmap(srcRect, *this, destRect); } S::Int S::GUI::Bitmap::BlitToSurface(const Rect &srcRect, Surface *surface, const Rect &destRect) const { if (surface == NIL) return Error(); return surface->BlitFromBitmap(*this, srcRect, destRect); } S::Bool S::GUI::Bitmap::SetPixel(const Point &point, const Color &color) { return backend->SetPixel(point, color); } S::GUI::Color S::GUI::Bitmap::GetPixel(const Point &point) const { return backend->GetPixel(point); } S::GUI::Bitmap &S::GUI::Bitmap::operator =(Void *iBitmap) { *backend = iBitmap; return *this; } S::GUI::Bitmap &S::GUI::Bitmap::operator =(const int nil) { *backend = nil; return *this; } S::GUI::Bitmap &S::GUI::Bitmap::operator =(const Bitmap &newBitmap) { *backend = *(newBitmap.backend); return *this; } S::Bool S::GUI::Bitmap::operator ==(const int nil) const { return (*backend == nil); } S::Bool S::GUI::Bitmap::operator !=(const int nil) const { return (*backend != nil); } S::Bool S::GUI::Bitmap::operator ==(const Bitmap &bitmap) const { if (*this == NIL && bitmap == NIL) return True; if (*this == NIL || bitmap == NIL) return False; if (GetSize() != bitmap.GetSize() || GetDepth() != bitmap.GetDepth() || GetBitsPerPixel() != bitmap.GetBitsPerPixel() || GetLineAlignment() != bitmap.GetLineAlignment()) return False; Size size = GetSize(); Int bpp = GetBitsPerPixel(); Int align = GetLineAlignment(); Int bpl = ((align - ((size.cx * (bpp / 8)) % align)) % align) + size.cx * (bpp / 8); Int bytes = bpl * size.cy; if (memcmp(GetBytes(), bitmap.GetBytes(), bytes) != 0) return False; return True; } S::Bool S::GUI::Bitmap::operator !=(const Bitmap &bitmap) const { return !(*this == bitmap); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/color.cpp000077500000000000000000000163311516402577000230460ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::GUI::Color S::GUI::Color::ConvertTo(ColorSpace cs) const { double p1 = 0; double p2 = 0; double p3 = 0; double p4 = 0; double r; double g; double b; double h; double s; double v; double min; double max; switch (colorSpace) { case RGB: switch (cs) { case RGB: return *this; case RGBA: return Color(255 << 24 | color, RGBA); case HSV: r = GetRed(); g = GetGreen(); b = GetBlue(); max = Math::Max(Math::Max(r, g), b); min = Math::Min(Math::Min(r, g), b); v = max; if (max != 0) s = (max - min) / max; else s = 0; h = 0; if (s != 0) { double delta = max - min; if (r == max) h = (g - b) / delta; else if (g == max) h = 2 + (b - r) / delta; else if (b == max) h = 4 + (r - g) / delta; h *= 60; if (h < 0) h += 360; } p1 = h / 360 * 255; p2 = s * 255; p3 = v; p1 = Math::Round(p1); p2 = Math::Round(p2); return Color((int) p1, (int) p2, (int) p3, HSV); case YUV: p1 = (GetRed() + GetGreen() + GetBlue()) / 3; p2 = GetBlue(); p3 = GetRed(); p1 = Math::Round(p1); return Color((int) p1, (int) p2, (int) p3, YUV); case CMY: p1 = 255 - GetRed(); p2 = 255 - GetGreen(); p3 = 255 - GetBlue(); return Color((int) p1, (int) p2, (int) p3, CMY); case CMYK: r = GetRed(); g = GetGreen(); b = GetBlue(); p4 = 255 - Math::Max(Math::Max(r, g), b); p1 = 255 - r - p4; p2 = 255 - g - p4; p3 = 255 - b - p4; return Color(((Int) p1) | ((Int) p2) << 8 | ((Int) p3) << 16 | ((Int) p4) << 24, CMYK); case GRAY: return Color((GetRed() + GetGreen() + GetBlue()) / 3, GRAY); default: break; } break; case RGBA: switch (cs) { case RGB: return Color(GetRed(), GetGreen(), GetBlue(), RGB); case RGBA: return *this; case HSV: return ConvertTo(RGB).ConvertTo(HSV); case YUV: return ConvertTo(RGB).ConvertTo(YUV); case CMY: return ConvertTo(RGB).ConvertTo(CMY); case CMYK: return ConvertTo(RGB).ConvertTo(CMYK); case GRAY: return ConvertTo(RGB).ConvertTo(GRAY); default: break; } break; case HSV: switch (cs) { case RGB: h = ((double) GetRed()) / 255 * 360; s = ((double) GetGreen()) / 255; v = GetBlue(); if (s == 0) { p1 = v; p2 = v; p3 = v; } else { while (h < 0) h += 360; while (h >= 360) h -= 360; h /= 60; double f = h - (int) h; double p = v * (1 - s ); double q = v * (1 - (s * f )); double t = v * (1 - (s * (1 - f))); switch ((int) h) { case 0: p1 = v; p2 = t; p3 = p; break; case 1: p1 = q; p2 = v; p3 = p; break; case 2: p1 = p; p2 = v; p3 = t; break; case 3: p1 = p; p2 = q; p3 = v; break; case 4: p1 = t; p2 = p; p3 = v; break; case 5: p1 = v; p2 = p; p3 = q; break; default: break; } } p1 = Math::Round(p1); p2 = Math::Round(p2); p3 = Math::Round(p3); return Color((int) p1, (int) p2, (int) p3, RGB); case RGBA: return ConvertTo(RGB).ConvertTo(RGBA); case HSV: return *this; case YUV: return ConvertTo(RGB).ConvertTo(YUV); case CMY: return ConvertTo(RGB).ConvertTo(CMY); case CMYK: return ConvertTo(RGB).ConvertTo(CMYK); case GRAY: return ConvertTo(RGB).ConvertTo(GRAY); default: break; } break; case YUV: switch (cs) { case RGB: p1 = GetBlue(); p3 = GetGreen(); p2 = 3 * GetRed() - p1 - p3; if (p2 < 0) p2 = 0; return Color((int) p1, (int) p2, (int) p3, RGB); case RGBA: return ConvertTo(RGB).ConvertTo(RGBA); case HSV: return ConvertTo(RGB).ConvertTo(HSV); case YUV: return *this; case CMY: return ConvertTo(RGB).ConvertTo(CMY); case CMYK: return ConvertTo(RGB).ConvertTo(CMYK); case GRAY: return ConvertTo(RGB).ConvertTo(GRAY); default: break; } break; case CMY: switch (cs) { case RGB: p1 = 255 - GetRed(); p2 = 255 - GetGreen(); p3 = 255 - GetBlue(); return Color((int) p1, (int) p2, (int) p3, RGB); case RGBA: return ConvertTo(RGB).ConvertTo(RGBA); case HSV: return ConvertTo(RGB).ConvertTo(HSV); case YUV: return ConvertTo(RGB).ConvertTo(YUV); case CMY: return *this; case CMYK: return ConvertTo(RGB).ConvertTo(CMYK); case GRAY: return ConvertTo(RGB).ConvertTo(GRAY); default: break; } break; case CMYK: switch (cs) { case RGB: p4 = GetAlpha(); p1 = 255 - GetRed() - p4; p2 = 255 - GetGreen() - p4; p3 = 255 - GetBlue() - p4; return Color((int) p1, (int) p2, (int) p3, RGB); case RGBA: return ConvertTo(RGB).ConvertTo(RGBA); case HSV: return ConvertTo(RGB).ConvertTo(HSV); case YUV: return ConvertTo(RGB).ConvertTo(YUV); case CMY: return ConvertTo(RGB).ConvertTo(CMY); case CMYK: return *this; case GRAY: return ConvertTo(RGB).ConvertTo(GRAY); default: break; } break; case GRAY: switch (cs) { case RGB: return Color(color, color, color, RGB); case RGBA: return ConvertTo(RGB).ConvertTo(RGBA); case HSV: return ConvertTo(RGB).ConvertTo(HSV); case YUV: return ConvertTo(RGB).ConvertTo(YUV); case CMY: return ConvertTo(RGB).ConvertTo(CMY); case CMYK: return ConvertTo(RGB).ConvertTo(CMYK); case GRAY: return *this; default: break; } break; default: break; } return *this; } S::GUI::Color S::GUI::Color::Downsample(Int bpcc) const { if (bpcc == 8) return *this; int first = GetRed(); int second = GetGreen(); int third = GetBlue(); first >>= (8 - bpcc); second >>= (8 - bpcc); third >>= (8 - bpcc); return Color((Long) (first + Math::Pow(2, bpcc) * second + Math::Pow(4, bpcc) * third), colorSpace); } S::GUI::Color S::GUI::Color::Upsample(Int bpcc) const { if (bpcc == 8) return *this; int first = color & (int) (Math::Pow(2, bpcc) - 1); int second = (color >> bpcc ) & (int) (Math::Pow(2, bpcc) - 1); int third = (color >> (2 * bpcc)) & (int) (Math::Pow(2, bpcc) - 1); first = (int) (255 / (Math::Pow(2, bpcc) - 1) * (double) first); second = (int) (255 / (Math::Pow(2, bpcc) - 1) * (double) second); third = (int) (255 / (Math::Pow(2, bpcc) - 1) * (double) third); return Color(first, second, third, colorSpace); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/font.cpp000066400000000000000000000075331516402577000226770ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2011 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::String S::GUI::Font::Default = "default"; S::Short S::GUI::Font::DefaultSize = 8; S::Short S::GUI::Font::Thin = 100; S::Short S::GUI::Font::ExtraLight = 200; S::Short S::GUI::Font::Light = 300; S::Short S::GUI::Font::Normal = 400; S::Short S::GUI::Font::Medium = 500; S::Short S::GUI::Font::SemiBold = 600; S::Short S::GUI::Font::Bold = 700; S::Short S::GUI::Font::ExtraBold = 800; S::Short S::GUI::Font::Black = 900; S::Short S::GUI::Font::Italic = 2; S::Short S::GUI::Font::Underline = 4; S::Short S::GUI::Font::StrikeOut = 8; S::GUI::Font::Font(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) { fontName = iFontName; fontSize = iFontSize; fontColor = iFontColor; fontWeight = iFontWeight; fontStyle = iFontStyle; backend = FontBackend::CreateBackendInstance(fontName, fontSize, fontWeight, fontStyle, fontColor); } S::GUI::Font::Font(const Font &iFont) { fontName = iFont.fontName; fontSize = iFont.fontSize; fontColor = iFont.fontColor; fontWeight = iFont.fontWeight; fontStyle = iFont.fontStyle; backend = FontBackend::CreateBackendInstance(fontName, fontSize, fontWeight, fontStyle, fontColor); } S::GUI::Font::~Font() { delete backend; } S::GUI::Font &S::GUI::Font::operator =(const Font &newFont) { SetName(newFont.GetName()); SetSize(newFont.GetSize()); SetColor(newFont.GetColor()); SetWeight(newFont.GetWeight()); SetStyle(newFont.GetStyle()); return *this; } S::Bool S::GUI::Font::operator ==(const Font &font) const { if (fontName == font.GetName() && fontSize == font.GetSize() && fontColor == font.GetColor() && fontWeight == font.GetWeight() && fontStyle == font.GetStyle()) return True; else return False; } S::Bool S::GUI::Font::operator !=(const Font &font) const { return !(*this == font); } S::Int S::GUI::Font::SetName(const String &newFontName) { backend->SetName(newFontName); fontName = newFontName; return Success(); } S::Int S::GUI::Font::SetSize(Short newFontSize) { backend->SetSize(newFontSize); fontSize = newFontSize; return Success(); } S::Int S::GUI::Font::SetColor(const Color &newFontColor) { backend->SetColor(newFontColor); fontColor = newFontColor; return Success(); } S::Int S::GUI::Font::SetWeight(Short newFontWeight) { backend->SetWeight(newFontWeight); fontWeight = newFontWeight; return Success(); } S::Int S::GUI::Font::SetStyle(Short newFontStyle) { backend->SetStyle(newFontStyle); fontStyle = newFontStyle; return Success(); } const S::String &S::GUI::Font::GetName() const { return fontName; } S::Short S::GUI::Font::GetSize() const { return fontSize; } const S::GUI::Color &S::GUI::Font::GetColor() const { return fontColor; } S::Short S::GUI::Font::GetWeight() const { return fontWeight; } S::Short S::GUI::Font::GetStyle() const { return fontStyle; } S::Int S::GUI::Font::GetUnscaledTextSizeX(const String &text) const { return backend->GetTextSizeX(text, False); } S::Int S::GUI::Font::GetUnscaledTextSizeY(const String &text) const { return backend->GetTextSizeY(text, False); } S::Int S::GUI::Font::GetScaledTextSizeX(const String &text) const { return backend->GetTextSizeX(text, True); } S::Int S::GUI::Font::GetScaledTextSizeY(const String &text) const { return backend->GetTextSizeY(text, True); } smooth-0.9.11~git20260403.0230c0da/classes/graphics/forms/000077500000000000000000000000001516402577000223435ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/forms/Makefile000066400000000000000000000004441516402577000240050ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = rect.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/forms/rect.cpp000077500000000000000000000032521516402577000240110ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2015 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::Int S::GUI::Rect::Outlined = 0; S::Int S::GUI::Rect::Filled = 1; S::Int S::GUI::Rect::Rounded = 2; S::Int S::GUI::Rect::Inverted = 4; S::Int S::GUI::Rect::Dotted = 8; S::Bool S::GUI::Rect::DoRectsOverlap(const Rect &rect1, const Rect &rect2) { if ((rect1.left < rect2.right ) && (rect1.right > rect2.left) && (rect1.top < rect2.bottom) && (rect1.bottom > rect2.top )) return True; else return False; } S::GUI::Rect S::GUI::Rect::OverlapRect(const Rect &rect1, const Rect &rect2) { if (DoRectsOverlap(rect1, rect2)) { Rect oRect; oRect.left = (Int) Math::Max(rect1.left, rect2.left); oRect.top = (Int) Math::Max(rect1.top, rect2.top); oRect.right = (Int) Math::Min(rect1.right, rect2.right); oRect.bottom = (Int) Math::Min(rect1.bottom, rect2.bottom); return oRect; } return Rect(); } S::GUI::Rect S::GUI::Rect::EncloseRect(const Rect &rect1, const Rect &rect2) { Rect eRect; eRect.left = (Int) Math::Min(rect1.left, rect2.left); eRect.top = (Int) Math::Min(rect1.top, rect2.top); eRect.right = (Int) Math::Max(rect1.right, rect2.right); eRect.bottom = (Int) Math::Max(rect1.bottom, rect2.bottom); return eRect; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/imageloader/000077500000000000000000000000001516402577000234665ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/imageloader/Makefile000066400000000000000000000021201516402577000251210ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifeq ($(USE_BUNDLED_LIBJPEG),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support/libjpeg else ifeq ($(BUILD_NETBSD),True) MYCCOPTS += -I/usr/pkg/include else MYCCOPTS += -I/usr/local/include endif ifeq ($(USE_BUNDLED_LIBPNG),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support/libpng else MYCCOPTS += $(shell pkg-config --cflags libpng) endif ifeq ($(USE_BUNDLED_LIBWEBP),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support/libwebp else MYCCOPTS += $(shell pkg-config --cflags libwebp) endif ifeq ($(BUILD_GDIPLUS),True) MYCCOPTS += -D HAVE_GDIPLUS=1 endif # Enter object files here: OBJECTS = imageloader.o jpeg.o pci.o png.o webp.o ifeq ($(BUILD_WIN32),True) OBJECTS += icon.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/imageloader/icon.cpp000077500000000000000000000060521516402577000251300ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #ifdef HAVE_GDIPLUS # include #endif S::GUI::ImageLoaderIcon::ImageLoaderIcon(const String &iFileName) : ImageLoader(iFileName) { } S::GUI::ImageLoaderIcon::~ImageLoaderIcon() { } const S::GUI::Bitmap &S::GUI::ImageLoaderIcon::Load() { Int iconID = fileName.Tail(fileName.Length() - 5).ToInt(); if (iconID == 0) return bitmap; /* Load icon resource. */ HICON icon = NIL; if (iconID >= 32512 && iconID <= 32517) icon = (HICON) LoadImage(NIL, MAKEINTRESOURCE(iconID), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); else if (iconID >= 20000 && iconID <= 20999) icon = (HICON) LoadImage(hDllInstance, MAKEINTRESOURCE(iconID), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); else icon = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(iconID), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); /* Create bitmap and draw icon. */ Size size(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); bitmap.CreateBitmap(size, 32); #ifdef HAVE_GDIPLUS Gdiplus::Bitmap *gdipBitmap = (Gdiplus::Bitmap *) bitmap.GetSystemBitmap(); Gdiplus::Graphics graphics(gdipBitmap); graphics.Clear(Gdiplus::Color::Transparent); HDC dc = graphics.GetHDC(); #else HDC dc = CreateCompatibleDC(NIL); HBITMAP backup = (HBITMAP) SelectObject(dc, bitmap.GetSystemBitmap()); #endif DrawIconEx(dc, 0, 0, icon, 0, 0, 0, NIL, DI_DEFAULTSIZE | DI_IMAGE | DI_MASK); /* Fix alpha channel for 8 bit icons. */ if (!IsAlphaChannelSet()) { SetBackgroundColor(Setup::BackgroundColor); DrawIconEx(dc, 0, 0, icon, 0, 0, 0, NIL, DI_DEFAULTSIZE | DI_IMAGE | DI_MASK); SetAlphaChannel(255); } /* Clean up. */ #ifdef HAVE_GDIPLUS graphics.ReleaseHDC(dc); #else SelectObject(dc, backup); DeleteDC(dc); #endif return bitmap; } S::Bool S::GUI::ImageLoaderIcon::IsAlphaChannelSet() const { Size size = bitmap.GetSize(); for (Int x = 0; x < size.cx; x++) { for (Int y = 0; y < size.cy; y++) { if (bitmap.GetPixel(Point(x, y)).GetAlpha() != 0) return True; } } return False; } S::Void S::GUI::ImageLoaderIcon::SetBackgroundColor(const Color &color) { Size size = bitmap.GetSize(); for (Int x = 0; x < size.cx; x++) { for (Int y = 0; y < size.cy; y++) { bitmap.SetPixel(Point(x, y), color); } } } S::Void S::GUI::ImageLoaderIcon::SetAlphaChannel(Int value) { Size size = bitmap.GetSize(); for (Int x = 0; x < size.cx; x++) { for (Int y = 0; y < size.cy; y++) { bitmap.SetPixel(Point(x, y), Color(value << 24 | bitmap.GetPixel(Point(x, y)), Color::RGBA)); } } } smooth-0.9.11~git20260403.0230c0da/classes/graphics/imageloader/imageloader.cpp000077500000000000000000000077351516402577000264620ustar00rootroot00000000000000/* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include using namespace smooth::IO; namespace smooth { namespace GUI { static Short DetectImageFormat(const Buffer &buffer) { Short format = IMAGE_FORMAT_AUTO; if (buffer.Size() < 12) return format; if (buffer[ 0] == 0x50 && buffer[ 1] == 0x43 && buffer[ 2] == 0x49 && buffer[ 3] == 0x46) format = IMAGE_FORMAT_PCI; else if (buffer[ 0] == 0xFF && buffer[ 1] == 0xD8) format = IMAGE_FORMAT_JPEG; else if (buffer[ 0] == 0x89 && buffer[ 1] == 0x50 && buffer[ 2] == 0x4E && buffer[ 3] == 0x47 && buffer[ 4] == 0x0D && buffer[ 5] == 0x0A && buffer[ 6] == 0x1A && buffer[ 7] == 0x0A) format = IMAGE_FORMAT_PNG; else if (buffer[ 0] == 0x52 && buffer[ 1] == 0x49 && buffer[ 2] == 0x46 && buffer[ 3] == 0x46 && buffer[ 8] == 0x57 && buffer[ 9] == 0x45 && buffer[10] == 0x42 && buffer[11] == 0x50) format = IMAGE_FORMAT_WEBP; return format; } }; }; S::GUI::ImageLoader::ImageLoader(const String &iFileName) { fileName = iFileName; gotFileName = True; gotBuffer = False; } S::GUI::ImageLoader::ImageLoader(const Buffer &iBuffer) { buffer = iBuffer; gotBuffer = True; gotFileName = False; } S::GUI::ImageLoader::~ImageLoader() { } S::GUI::Bitmap S::GUI::ImageLoader::Load(const String &fileName) { ImageLoader *loader = NIL; if (fileName.ToLower().Contains(".pci:")) loader = new ImageLoaderPCI(fileName); #ifdef __WIN32__ else if (fileName.StartsWith("Icon:")) loader = new ImageLoaderIcon(fileName); #endif if (loader == NIL) { /* Auto-detect image format. */ Buffer buffer(12); InStream in(STREAM_FILE, fileName, IS_READ); in.InputData(buffer, 12); Short format = DetectImageFormat(buffer); if (format == IMAGE_FORMAT_PCI) loader = new ImageLoaderPCI(fileName); else if (format == IMAGE_FORMAT_PNG) loader = new ImageLoaderPNG(fileName); else if (format == IMAGE_FORMAT_JPEG) loader = new ImageLoaderJPEG(fileName); else if (format == IMAGE_FORMAT_WEBP) loader = new ImageLoaderWebP(fileName); } /* Load image. */ Bitmap bitmap; if (loader != NIL) { bitmap = loader->Load(); delete loader; } /* Look in the startup and application folders if no image has been found yet. */ if (!fileName.StartsWith(Application::GetStartupDirectory()) && !fileName.StartsWith(Application::GetApplicationDirectory())) { if (bitmap == NIL) bitmap = Load(Application::GetStartupDirectory().Append(fileName)); if (bitmap == NIL) bitmap = Load(Application::GetApplicationDirectory().Append(fileName)); } return bitmap; } S::GUI::Bitmap S::GUI::ImageLoader::Load(const Buffer &buffer, Short format) { /* Auto-detect image format. */ if (format == IMAGE_FORMAT_AUTO) format = DetectImageFormat(buffer); /* Create image loader. */ ImageLoader *loader = NIL; if (format == IMAGE_FORMAT_PCI) loader = new ImageLoaderPCI(buffer); else if (format == IMAGE_FORMAT_PNG) loader = new ImageLoaderPNG(buffer); else if (format == IMAGE_FORMAT_JPEG) loader = new ImageLoaderJPEG(buffer); else if (format == IMAGE_FORMAT_WEBP) loader = new ImageLoaderWebP(buffer); if (loader == NIL) return NIL; Bitmap bitmap = loader->Load(); delete loader; return bitmap; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/imageloader/jpeg.cpp000077500000000000000000000115371516402577000251310ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include extern "C" { # include # include } using namespace smooth::IO; S::GUI::ImageLoaderJPEG::ImageLoaderJPEG(const String &iFileName) : ImageLoader(iFileName) { } S::GUI::ImageLoaderJPEG::ImageLoaderJPEG(const Buffer &iBuffer) : ImageLoader(iBuffer) { } S::GUI::ImageLoaderJPEG::~ImageLoaderJPEG() { } void my_error_exit(j_common_ptr cinfo) { } const S::GUI::Bitmap &S::GUI::ImageLoaderJPEG::Load() { /* Make sure bitmap is initialized. */ bitmap = NIL; /* Check magic number. */ if ( gotBuffer && (buffer[0] != 0xFF || buffer[1] != 0xD8)) return bitmap; else if (!gotBuffer && InStream(STREAM_FILE, fileName, IS_READ).InputNumberRaw(2) != 0xFFD8) return bitmap; /* Open stream. */ FILE *stream = NIL; if (!gotBuffer) { #ifdef __WIN32__ stream = _wfopen(fileName, L"rb"); #else stream = fopen(fileName.ConvertTo("UTF-8"), "rb"); #endif if (stream == NIL) return bitmap; } /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ jpeg_decompress_struct cinfo; /* We set up the normal JPEG error routines, then override error_exit. */ jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); cinfo.err->error_exit = my_error_exit; /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); /* Specify data source (eg, a file) */ if (gotBuffer) jpeg_mem_src(&cinfo, buffer, buffer.Size()); else jpeg_stdio_src(&cinfo, stream); /* Read file parameters with jpeg_read_header() */ if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) { jpeg_destroy_decompress(&cinfo); if (!gotBuffer) fclose(stream); return bitmap; } /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Start decompressor */ jpeg_start_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ int row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that will go away when done with image */ JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); bitmap.CreateBitmap(Size(cinfo.output_width, cinfo.output_height)); /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ jpeg_read_scanlines(&cinfo, buffer, 1); /* TODO: The copying step needs lots of optimization */ for (Int x = 0; x < (signed) cinfo.output_width; x++) { bitmap.SetPixel(Point(x, cinfo.output_scanline - 1), Color(buffer[0][3 * x], buffer[0][3 * x + 1], buffer[0][3 * x + 2], Color::RGB)); } } /* We can ignore the return value since suspension is not possible * with the stdio data source. */ jpeg_finish_decompress(&cinfo); /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ if (!gotBuffer) fclose(stream); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). */ /* And we're done! */ return bitmap; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/imageloader/pci.cpp000077500000000000000000000026641516402577000247600ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::GUI::ImageLoaderPCI::ImageLoaderPCI(const String &iFileName) : ImageLoader(iFileName) { } S::GUI::ImageLoaderPCI::ImageLoaderPCI(const Buffer &iBuffer) : ImageLoader(iBuffer) { } S::GUI::ImageLoaderPCI::~ImageLoaderPCI() { } const S::GUI::Bitmap &S::GUI::ImageLoaderPCI::Load() { /* Make sure bitmap is initialized. */ bitmap = NIL; /* Load PCI file. */ String pciFile = fileName; String idString; pciFile[fileName.ToLower().Find(".pci:") + 4] = 0; for (Int i = 0; i < fileName.Length() - fileName.ToLower().Find(".pci:") - 5; i++) idString[i] = fileName[fileName.ToLower().Find(".pci:") + 5 + i]; Int id = idString.ToInt(); PCIIn pci = OpenPCIForInput(pciFile); if (pci->GetLastError() != IO::IO_ERROR_OK) { ClosePCI(pci); return bitmap; } PCIIO *pio = new PCIIO(); pio->SelectImage(id); pio->ReadPCI(pci); ClosePCI(pci); bitmap = pio->GetBitmap(); delete pio; return bitmap; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/imageloader/png.cpp000077500000000000000000000146111516402577000247640ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include using namespace smooth::IO; S::GUI::ImageLoaderPNG::ImageLoaderPNG(const String &iFileName) : ImageLoader(iFileName) { } S::GUI::ImageLoaderPNG::ImageLoaderPNG(const Buffer &iBuffer) : ImageLoader(iBuffer) { } S::GUI::ImageLoaderPNG::~ImageLoaderPNG() { } void my_png_error(png_structp png_ptr, png_const_charp error) { } void my_png_warning(png_structp png_ptr, png_const_charp warning) { } void my_png_read(png_structp png_ptr, png_bytep buffer, png_size_t size) { InStream *in = (InStream *) png_get_io_ptr(png_ptr); in->InputData(buffer, size); } const S::GUI::Bitmap &S::GUI::ImageLoaderPNG::Load() { /* Make sure bitmap is initialized. */ bitmap = NIL; /* Check if we either have a file or a buffer to load. */ if (!gotFileName && !gotBuffer) return bitmap; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. */ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NIL, &my_png_error, &my_png_warning); if (png_ptr == NULL) return bitmap; /* Allocate/initialize the memory for image information. */ png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, NULL, NULL); return bitmap; } /* Create input stream for file or buffer. */ InStream *in = NIL; if (gotFileName) in = new InStream(STREAM_FILE, fileName, IS_READ); else if (gotBuffer) in = new InStream(STREAM_BUFFER, buffer, buffer.Size()); if (in->GetLastError() != IO_ERROR_OK || in->InputNumberRaw(8) != (Int64) 0x89504E470D0A1A0ALL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); delete in; return bitmap; } in->Seek(0); /* If you are using replacement read functions, instead of calling * png_init_io() here you would call: */ png_set_read_fn(png_ptr, (void *) in, &my_png_read); /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); /* Tell libpng to strip 16 bit/color files down to 8 bits/color. */ png_set_strip_16(png_ptr); /* Get basic image information and create bitmap. */ png_uint_32 width = 0; png_uint_32 height = 0; int bit_depth = 0; int color_type = 0; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); bitmap.CreateBitmap(Size(width, height), (color_type == PNG_COLOR_TYPE_RGB_ALPHA || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ? 32 : 24); /* Set background color if the image has an alpha * channel but we only have a non-alpha bitmap. */ if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) && bitmap.GetDepth() != 32) { /* Set the background color to draw transparent and alpha images over. * It is possible to set the red, green, and blue components directly * for paletted images instead of supplying a palette index. */ png_color_16 my_background; my_background.red = Setup::BackgroundColor.GetRed(); my_background.green = Setup::BackgroundColor.GetGreen(); my_background.blue = Setup::BackgroundColor.GetBlue(); png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) color_type = PNG_COLOR_TYPE_RGB; else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) color_type = PNG_COLOR_TYPE_GRAY; } /* Get palette information. */ png_colorp palette = NULL; int num_palette = 0; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); /* The easiest way to read the image. */ png_bytep *row_pointers = (png_bytep *) malloc(height * sizeof(png_bytep)); for (unsigned int row = 0; row < height; row++) row_pointers[row] = (png_bytep) malloc(png_get_rowbytes(png_ptr, info_ptr)); /* Now it's time to read the image. */ png_read_image(png_ptr, row_pointers); for (UnsignedInt y = 0; y < height; y++) { for (UnsignedInt x = 0; x < width; x++) { if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 1) bitmap.SetPixel(Point(x, y), Color(row_pointers[y][x / 8] & (128 >> (x % 8)) ? 255 : 0, Color::GRAY)); else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color( row_pointers[y][ x ] << 16 | row_pointers[y][ x ] << 8 | row_pointers[y][ x], Color::RGB)); else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color(row_pointers[y][2 * x + 1] << 24 | row_pointers[y][2 * x ] << 16 | row_pointers[y][2 * x ] << 8 | row_pointers[y][2 * x], Color::RGBA)); else if (color_type == PNG_COLOR_TYPE_RGB && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color( row_pointers[y][3 * x + 2] << 16 | row_pointers[y][3 * x + 1] << 8 | row_pointers[y][3 * x], Color::RGB)); else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color(row_pointers[y][4 * x + 3] << 24 | row_pointers[y][4 * x + 2] << 16 | row_pointers[y][4 * x + 1] << 8 | row_pointers[y][4 * x], Color::RGBA)); else if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color(palette[row_pointers[y][x]].red, palette[row_pointers[y][x]].green, palette[row_pointers[y][x]].blue, Color::RGB)); } } /* Free PNG rows. */ for (unsigned int row = 0; row < height; row++) free(row_pointers[row]); free(row_pointers); /* Read rest of file, and get additional chunks in info_ptr. */ png_read_end(png_ptr, info_ptr); /* Clean up after the read, and free any memory allocated. */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); delete in; /* That's it. */ return bitmap; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/imageloader/webp.cpp000066400000000000000000000041651516402577000251350ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include using namespace smooth::IO; S::GUI::ImageLoaderWebP::ImageLoaderWebP(const String &iFileName) : ImageLoader(iFileName) { } S::GUI::ImageLoaderWebP::ImageLoaderWebP(const Buffer &iBuffer) : ImageLoader(iBuffer) { } S::GUI::ImageLoaderWebP::~ImageLoaderWebP() { } const S::GUI::Bitmap &S::GUI::ImageLoaderWebP::Load() { /* Make sure bitmap is initialized. */ bitmap = NIL; /* Check if we either have a file or a buffer to load. */ if (!gotFileName && !gotBuffer) return bitmap; /* Load file into buffer. */ if (gotFileName) { InStream in(STREAM_FILE, fileName, IS_READ); buffer.Resize(in.Size()); in.InputData(buffer, buffer.Size()); } /* Init WebP decoder. */ WebPDecoderConfig config; WebPInitDecoderConfig(&config); if (WebPGetFeatures(buffer, buffer.Size(), &config.input) != VP8_STATUS_OK) return bitmap; /* Decode image in RGBA format. */ config.output.colorspace = MODE_RGBA; if (WebPDecode(buffer, buffer.Size(), &config) != VP8_STATUS_OK) return bitmap; /* Copy decoded image to bitmap. */ bitmap.CreateBitmap(Size(config.input.width, config.input.height)); for (Int y = 0; y < config.input.height; y++) { Int lineOffset = 4 * y * config.input.width; for (Int x = 0; x < config.input.width; x++) { bitmap.SetPixel(Point(x, y), Color(config.output.u.RGBA.rgba[lineOffset + 4 * x + 3] << 24 | config.output.u.RGBA.rgba[lineOffset + 4 * x + 2] << 16 | config.output.u.RGBA.rgba[lineOffset + 4 * x + 1] << 8 | config.output.u.RGBA.rgba[lineOffset + 4 * x], Color::RGBA)); } } WebPFreeDecBuffer(&config.output); return bitmap; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/modifiers/000077500000000000000000000000001516402577000231765ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/graphics/modifiers/Makefile000066400000000000000000000004661516402577000246440ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = fontsize.o righttoleft.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/graphics/modifiers/fontsize.cpp000077500000000000000000000022251516402577000255470ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2010 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::GUI::FontSizeModifier::FontSizeModifier() { fontSize = 96; } S::GUI::FontSizeModifier::~FontSizeModifier() { } S::Int S::GUI::FontSizeModifier::TranslateX(Int x) const { return x * fontSize / 96; } S::Int S::GUI::FontSizeModifier::TranslateY(Int y) const { return y * fontSize / 96; } S::GUI::Point S::GUI::FontSizeModifier::TranslatePoint(const Point &p) const { return p * fontSize / 96; } S::GUI::Rect S::GUI::FontSizeModifier::TranslateRect(const Rect &r) const { return r * fontSize / 96; } S::Void S::GUI::FontSizeModifier::SetFontSize(Short nFontSize) { fontSize = nFontSize; } S::Short S::GUI::FontSizeModifier::GetFontSize() const { return fontSize; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/modifiers/righttoleft.cpp000077500000000000000000000031701516402577000262410ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2012 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::GUI::RightToLeftModifier::RightToLeftModifier() { surfaceSize = Size(0, 0); rightToLeft = False; } S::GUI::RightToLeftModifier::~RightToLeftModifier() { } S::Int S::GUI::RightToLeftModifier::TranslateX(Int x) const { if (rightToLeft) return surfaceSize.cx - x; else return x; } S::Int S::GUI::RightToLeftModifier::TranslateY(Int y) const { return y; } S::GUI::Point S::GUI::RightToLeftModifier::TranslatePoint(const Point &p) const { if (rightToLeft) return Point(surfaceSize.cx - p.x, p.y); else return p; } S::GUI::Rect S::GUI::RightToLeftModifier::TranslateRect(const Rect &r) const { if (rightToLeft) return Rect(Point(surfaceSize.cx - r.right, r.top), r.GetSize()); else return Rect(Point( r.left, r.top), r.GetSize()); } S::Void S::GUI::RightToLeftModifier::SetSurfaceSize(const Size &nSurfaceSize) { surfaceSize = nSurfaceSize; } const S::GUI::Size &S::GUI::RightToLeftModifier::GetSurfaceSize() const { return surfaceSize; } S::Void S::GUI::RightToLeftModifier::SetRightToLeft(Bool nRightToLeft) { rightToLeft = nRightToLeft; } S::Bool S::GUI::RightToLeftModifier::GetRightToLeft() const { return rightToLeft; } smooth-0.9.11~git20260403.0230c0da/classes/graphics/surface.cpp000066400000000000000000000100611516402577000233470ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2012 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include S::GUI::Surface *S::GUI::Surface::nullSurface = NIL; S::Int addSurfaceInitTmp = S::AddInitFunction(&S::GUI::Surface::Initialize); S::Int addSurfaceFreeTmp = S::AddFreeFunction(&S::GUI::Surface::Free); S::GUI::Surface::Surface(Void *iSurface, const Size &maxSize) { backend = SurfaceBackend::CreateBackendInstance(iSurface, maxSize); } S::GUI::Surface::~Surface() { delete backend; } S::Int S::GUI::Surface::Initialize() { nullSurface = new Surface(); return Success(); } S::Int S::GUI::Surface::Free() { delete nullSurface; nullSurface = NIL; return Success(); } S::GUI::Surface *S::GUI::Surface::GetNullSurface() { return nullSurface; } S::Short S::GUI::Surface::GetSurfaceType() const { return backend->GetSurfaceType(); } S::Int S::GUI::Surface::SetSize(const Size &nSize) { backend->Lock(); Int rVal = backend->SetSize(nSize); backend->Release(); return rVal; } const S::GUI::Size &S::GUI::Surface::GetSize() const { return backend->GetSize(); } S::Int S::GUI::Surface::SetRightToLeft(Bool nRightToLeft) { return backend->SetRightToLeft(nRightToLeft); } S::Int S::GUI::Surface::PaintRect(const Rect &pRect) { backend->Lock(); Int rVal = backend->PaintRect(pRect); backend->Release(); return rVal; } S::Int S::GUI::Surface::StartPaint(const Rect &pRect) { backend->Lock(); Int rVal = backend->StartPaint(pRect); return rVal; } S::Int S::GUI::Surface::EndPaint() { Int rVal = backend->EndPaint(); backend->Release(); return rVal; } S::Void *S::GUI::Surface::GetSystemSurface() const { return backend->GetSystemSurface(); } S::Short S::GUI::Surface::GetSurfaceDPI() const { return backend->GetSurfaceDPI(); } S::Int S::GUI::Surface::SetPixel(const Point &point, const Color &color) { backend->Lock(); Int rVal = backend->SetPixel(point, color); backend->Release(); return rVal; } S::Int S::GUI::Surface::Line(const Point &pos1, const Point &pos2, const Color &color) { backend->Lock(); Int rVal = backend->Line(pos1, pos2, color); backend->Release(); return rVal; } S::Int S::GUI::Surface::Frame(const Rect &rect, Short style) { backend->Lock(); Int rVal = backend->Frame(rect, style); backend->Release(); return rVal; } S::Int S::GUI::Surface::Box(const Rect &rect, const Color &color, Int style, const Size &ellipse) { backend->Lock(); Int rVal = backend->Box(rect, color, style, ellipse); backend->Release(); return rVal; } S::Int S::GUI::Surface::SetText(const String &string, const Rect &rect, const Font &font, Bool shadow) { backend->Lock(); Int rVal = backend->SetText(string, rect, font, shadow); backend->Release(); return rVal; } S::Int S::GUI::Surface::Gradient(const Rect &rect, const Color &color1, const Color &color2, Int style) { backend->Lock(); Int rVal = backend->Gradient(rect, color1, color2, style); backend->Release(); return rVal; } S::Int S::GUI::Surface::Bar(const Point &p1, const Point &p2, Int orientation) { backend->Lock(); Int rVal = backend->Bar(p1, p2, orientation); backend->Release(); return rVal; } S::Int S::GUI::Surface::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &destRect) { backend->Lock(); Int rVal = backend->BlitFromBitmap(bitmap, srcRect, destRect); backend->Release(); return rVal; } S::Int S::GUI::Surface::BlitToBitmap(const Rect &srcRect, Bitmap &bitmap, const Rect &destRect) { backend->Lock(); Int rVal = backend->BlitToBitmap(srcRect, bitmap, destRect); backend->Release(); return rVal; } smooth-0.9.11~git20260403.0230c0da/classes/gui/000077500000000000000000000000001516402577000202015ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/Makefile000066400000000000000000000007201516402577000216400ustar00rootroot00000000000000########## smooth directory $(MAKE)file ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options FOLDERS = application clipboard dialogs widgets window .PHONY: $(FOLDERS) all: $(FOLDERS) $(FOLDERS): + $(call makein,$@) clean: $(foreach FOLDER,$(FOLDERS),$(FOLDER)##clean) $(foreach FOLDER,$(FOLDERS),$(FOLDER)##clean): $(call cleanin,$(subst ##clean,,$@)) smooth-0.9.11~git20260403.0230c0da/classes/gui/application/000077500000000000000000000000001516402577000225045ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/application/Makefile000066400000000000000000000006631516402577000241510ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = application.o ifeq ($(BUILD_WIN32),True) OBJECTS += xulloader.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/application/application.cpp000077500000000000000000000175151516402577000255270ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2023 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #if defined __WIN32__ # include #elif defined __HAIKU__ # include # include # include # include #else # include # include # include # include # if defined __APPLE__ # include # elif defined __FreeBSD__ # include # endif # ifndef PATH_MAX # define PATH_MAX 32768 # endif #endif const S::Short S::GUI::Application::classID = S::Object::RequestClassID(); S::String S::GUI::Application::command; S::Array S::GUI::Application::args; S::String S::GUI::Application::startupDirectory; S::String S::GUI::Application::applicationDirectory; S::Float S::GUI::Application::scaleFactor = 0.0; S::GUI::Application::Application(const String &name) : Widget(Point(0, 0), System::Screen::GetActiveScreenMetrics().GetSize()) { type = classID; text = name == NIL ? String("smooth Application") : name; Show(); } S::GUI::Application::~Application() { } S::Int S::GUI::Application::Loop() { static Bool firstTime = True; if (firstTime) { firstTime = False; /* Show pending windows when we are called for the first time. */ for (Int i = 0; i < Window::GetNOfWindows(); i++) { Window *window = Window::GetNthWindow(i); if (window != NIL && !window->IsVisibilitySet()) window->Show(); } } /* Enter main application loop. */ System::EventProcessor event; while (GUI::Window::nOfActiveWindows > 0) { if (!event.ProcessNextEvent()) break; } return Success(); } S::Void S::GUI::Application::SetArguments(const Array &nArgs) { foreach (const String &arg, nArgs) { /* Filter out scale factor argument. */ if (arg.StartsWith("--scale:")) { scaleFactor = arg.Tail(arg.Length() - 8).ToFloat(); continue; } /* Add to arguments array. */ args.Add(arg); } } S::String S::GUI::Application::GetStartupDirectory() { if (startupDirectory != NIL) return startupDirectory; #ifdef __WIN32__ Buffer buffer(32768 + 1); if (GetCurrentDirectory(buffer.Size(), buffer)) startupDirectory = buffer; if (!startupDirectory.EndsWith("\\")) startupDirectory.Append("\\"); #else Buffer buffer(PATH_MAX + 1); if (getcwd(buffer, buffer.Size()) != NIL) startupDirectory = buffer; if (!startupDirectory.EndsWith("/")) startupDirectory.Append("/"); #endif return startupDirectory; } S::String S::GUI::Application::GetApplicationDirectory() { if (applicationDirectory != NIL) return applicationDirectory; #if defined __WIN32__ Buffer buffer(32768 + 1); #else Buffer buffer(PATH_MAX + 1); #endif buffer.Zero(); #if defined __WIN32__ /* On Windows, use GetModuleFileName to get the exe file name. */ GetModuleFileName(NIL, buffer, buffer.Size() - 1); applicationDirectory = buffer; #elif defined __APPLE__ /* On macOS, get the path using the proc_pidpath call. */ if (proc_pidpath(getpid(), buffer, buffer.Size()) > 0) applicationDirectory = buffer; /* Resort to using lsof -p , which returns the path to the current binary in the first * txt section, in case lookup failed or we got the path to the Rosetta binary translator. */ if (applicationDirectory == NIL || applicationDirectory == "/usr/libexec/oah/translate") { FILE *pstdin = popen(String("lsof -p ").Append(String::FromInt(getpid())).Append(" | awk '$4 == \"txt\" { print substr($0, index($0, $9)) }'"), "r"); if (fscanf(pstdin, String("%[^\n]").Append(String::FromInt(buffer.Size() - 1)), (char *) buffer) > 0) applicationDirectory = buffer; pclose(pstdin); } #elif defined __FreeBSD__ /* On FreeBSD, the KERN_PROC_PATHNAME sysctl with pid -1 provides the path to the current binary. */ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; size_t len = buffer.Size(); if (sysctl(mib, 4, buffer, &len, NULL, 0) == 0) applicationDirectory = buffer; #elif defined __sun /* On Solaris, /proc//path/a.out links to the current binary. */ if (readlink(String("/proc/").Append(String::FromInt(getpid())).Append("/path/a.out"), buffer, buffer.Size() - 1) > 0) applicationDirectory = buffer; #elif defined __linux__ || defined __NetBSD__ /* On Linux and NetBSD, /proc//exe links to the current binary. */ if (readlink(String("/proc/").Append(String::FromInt(getpid())).Append("/exe"), buffer, buffer.Size() - 1) > 0) applicationDirectory = buffer; #elif defined __HAIKU__ /* On Haiku, get the path from application info. */ BApplication *app = Backends::BackendHaiku::GetApplication(); app_info ai; if (app->GetAppInfo(&ai) == B_OK) applicationDirectory.ImportFrom("UTF-8", BPath(&ai.ref).Path()); #endif if (applicationDirectory == NIL) { /* No system specific way to get the current binary path. * Try concatenating the startup directory and command. */ String binary = (command.StartsWith("/") ? String() : GetStartupDirectory()).Append(command).Replace("/./", "/"); if (!File(binary).Exists()) { /* Search the path for command. */ String path = getenv("PATH"); const Array &paths = path.Explode(":"); foreach (const String &path, paths) { /* Check for command in this path. */ if (File(String(path).Append("/").Append(command)).Exists()) { binary = String(path).Append("/").Append(command); break; } } } applicationDirectory = binary; } applicationDirectory[applicationDirectory.FindLast(Directory::GetDirectoryDelimiter()) + 1] = 0; #if defined __APPLE__ /* Change the returned path to Resources for macOS application bundles. */ if (applicationDirectory.EndsWith(".app/Contents/MacOS/")) applicationDirectory.Replace(".app/Contents/MacOS/", ".app/Contents/Resources/"); #endif return applicationDirectory; } namespace smooth { static Threads::Mutex *mutex = NIL; static UnsignedInt32 owner = UnsignedInt32(-1); static multithread (intptr_t) lockCount = 0; }; S::Int addApplicationInitTmp = S::AddInitFunction(&S::GUI::Application::Lock::Initialize); S::Int addApplicationFreeTmp = S::AddFreeFunction(&S::GUI::Application::Lock::Free); S::Int S::GUI::Application::Lock::Initialize() { mutex = new Threads::Mutex(); return Success(); } S::Int S::GUI::Application::Lock::Free() { delete mutex; mutex = NIL; return Success(); } S::Bool S::GUI::Application::Lock::Acquire() { if (!mutex->Lock()) return False; if (!lockCount++) owner = Threads::Thread::GetCurrentThreadID(); return True; } S::Bool S::GUI::Application::Lock::Release() { if (!lockCount) return False; if (!--lockCount) owner = UnsignedInt32(-1); return mutex->Release(); } S::Int S::GUI::Application::Lock::SuspendLock() { if (GetOwnerThreadID() != Threads::Thread::GetCurrentThreadID()) return 0; /* Release currently held lock. */ Int suspendCount = lockCount; for (Int i = 0; i < suspendCount; i++) Release(); return suspendCount; } S::Bool S::GUI::Application::Lock::ResumeLock(Int resumeCount) { if (resumeCount == 0) return False; /* Acquire lock. */ for (Int i = 0; i < resumeCount; i++) Acquire(); return True; } S::UnsignedInt32 S::GUI::Application::Lock::GetOwnerThreadID() { return owner; } smooth-0.9.11~git20260403.0230c0da/classes/gui/application/xulloader.cpp000077500000000000000000000032741516402577000252200ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #ifdef __WIN32__ # include void WINAPI S::GUI::LoadXUL(HWND hWnd, HINSTANCE shInstance, LPSTR szCmdLine, int iCmdShow) { hInstance = shInstance; /* Parse command line arguments. */ ArgumentsParser args(GetCommandLineW()); String command = args.GetCommand(); Array arguments = args.GetArguments(); if (arguments.GetFirst().EndsWith(".dll,LoadXUL")) { command = command.Append(" ").Append(arguments.GetFirst()); arguments.RemoveNth(0); } /* Init application and start XUL loader. */ Application::SetCommand(command); Application::SetArguments(arguments); Application::GetStartupDirectory(); Application::GetApplicationDirectory(); Init(); XULLoader *loader = new XULLoader(arguments.GetLast()); loader->Loop(); Object::DeleteObject(loader); Free(); } #endif S::GUI::XULLoader::XULLoader(const String &xulFile) { xulRenderer = new XML::XUL::Renderer(); if (xulRenderer->LoadXUL(xulFile) == Success()) Add(xulRenderer->GetWidget()); } S::GUI::XULLoader::~XULLoader() { delete xulRenderer; } smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/000077500000000000000000000000001516402577000221405ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/Makefile000066400000000000000000000006551516402577000236060ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = clipboard.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,backends) CLEANCMD1 = $(call cleanin,backends) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/000077500000000000000000000000001516402577000237125ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/Makefile000066400000000000000000000011701516402577000253510ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. # Enter object files here: OBJECTS = clipboardbackend.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,cocoa) ALLCMD2 = $(call makein,haiku) ALLCMD3 = $(call makein,win32) ALLCMD4 = $(call makein,xlib) CLEANCMD1 = $(call cleanin,cocoa) CLEANCMD2 = $(call cleanin,haiku) CLEANCMD3 = $(call cleanin,win32) CLEANCMD4 = $(call cleanin,xlib) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/clipboardbackend.cpp000066400000000000000000000034261516402577000276720ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2012 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::GUI::ClipboardBackend *CreateClipboardBackend(S::GUI::Window *window) { return new S::GUI::ClipboardBackend(); } S::GUI::ClipboardBackend *(*S::GUI::ClipboardBackend::backend_creator)(Window *) = &CreateClipboardBackend; S::Int S::GUI::ClipboardBackend::SetBackend(ClipboardBackend *(*backend)(Window *)) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::GUI::ClipboardBackend *S::GUI::ClipboardBackend::CreateBackendInstance(Window *window) { return backend_creator(window); } S::GUI::ClipboardBackend::ClipboardBackend() { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) ClipboardWin32(NIL); #endif type = CLIPBOARD_NONE; } S::GUI::ClipboardBackend::~ClipboardBackend() { } S::Short S::GUI::ClipboardBackend::GetClipboardType() const { return type; } S::String S::GUI::ClipboardBackend::GetSelectionText() const { return NIL; } S::Bool S::GUI::ClipboardBackend::SetSelectionText(const String &text) { return False; } S::String S::GUI::ClipboardBackend::GetClipboardText() const { return NIL; } S::Bool S::GUI::ClipboardBackend::SetClipboardText(const String &text) { return False; } smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/cocoa/000077500000000000000000000000001516402577000247765ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/cocoa/Makefile000066400000000000000000000006571516402577000264460ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_OSX),True) OBJECTS += clipboardcocoa.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/cocoa/clipboardcocoa.mm000066400000000000000000000033601516402577000302770ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2011 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::GUI::ClipboardBackend *CreateClipboardCocoa(S::GUI::Window *window) { return new S::GUI::ClipboardCocoa(window); } S::Int clipboardCocoaTmp = S::GUI::ClipboardBackend::SetBackend(&CreateClipboardCocoa); S::GUI::ClipboardCocoa::ClipboardCocoa(Window *iWindow) { type = CLIPBOARD_COCOA; window = iWindow; } S::GUI::ClipboardCocoa::~ClipboardCocoa() { } S::String S::GUI::ClipboardCocoa::GetClipboardText() const { if (window == NIL) return NIL; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; String clipboardText; NSString *clipboardString = [[NSPasteboard generalPasteboard] stringForType: NSStringPboardType]; if (clipboardString != NIL) clipboardText.ImportFrom("UTF-8", [clipboardString UTF8String]); [pool release]; return clipboardText; } S::Bool S::GUI::ClipboardCocoa::SetClipboardText(const String &text) { if (window == NIL) return False; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [[NSPasteboard generalPasteboard] declareTypes: [NSArray arrayWithObject: NSStringPboardType] owner: nil]; [[NSPasteboard generalPasteboard] setString: [NSString stringWithUTF8String: text.ConvertTo("UTF-8")] forType: NSStringPboardType]; [pool release]; return True; } smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/haiku/000077500000000000000000000000001516402577000250135ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/haiku/Makefile000066400000000000000000000006611516402577000264560ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_HAIKU),True) OBJECTS += clipboardhaiku.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/haiku/clipboardhaiku.cpp000066400000000000000000000035341516402577000305050ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::GUI::ClipboardBackend *CreateClipboardHaiku(S::GUI::Window *window) { return new S::GUI::ClipboardHaiku(window); } S::Int clipboardHaikuTmp = S::GUI::ClipboardBackend::SetBackend(&CreateClipboardHaiku); S::GUI::ClipboardHaiku::ClipboardHaiku(Window *iWindow) { type = CLIPBOARD_HAIKU; window = iWindow; } S::GUI::ClipboardHaiku::~ClipboardHaiku() { } S::String S::GUI::ClipboardHaiku::GetClipboardText() const { if (window == NIL) return NIL; String clipboardText; if (be_clipboard->Lock()) { BMessage *clip = be_clipboard->Data(); const void *data = NIL; ssize_t length = 0; if (clip->FindData("text/plain", B_MIME_TYPE, &data, &length) == B_OK) { Buffer buffer(length + 1); buffer.Zero(); memcpy(buffer, data, length); clipboardText.ImportFrom("UTF-8", buffer); } be_clipboard->Unlock(); } return clipboardText; } S::Bool S::GUI::ClipboardHaiku::SetClipboardText(const String &text) { if (window == NIL) return False; if (be_clipboard->Lock()) { be_clipboard->Clear(); if (text != NIL) { BMessage *clip = be_clipboard->Data(); const char *string = text.ConvertTo("UTF-8"); if (clip->AddData("text/plain", B_MIME_TYPE, string, strlen(string)) == B_OK) be_clipboard->Commit(); } be_clipboard->Unlock(); } return True; } smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/win32/000077500000000000000000000000001516402577000246545ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/win32/Makefile000066400000000000000000000006611516402577000263170ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_WIN32),True) OBJECTS += clipboardwin32.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/win32/clipboardwin32.cpp000066400000000000000000000037741516402577000302150ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::GUI::ClipboardBackend *CreateClipboardWin32(S::GUI::Window *window) { return new S::GUI::ClipboardWin32(window); } S::Int clipboardWin32Tmp = S::GUI::ClipboardBackend::SetBackend(&CreateClipboardWin32); S::GUI::ClipboardWin32::ClipboardWin32(Window *iWindow) { type = CLIPBOARD_WIN32; window = iWindow; } S::GUI::ClipboardWin32::~ClipboardWin32() { } S::String S::GUI::ClipboardWin32::GetClipboardText() const { if (window == NIL) return NIL; String clipboardText; OpenClipboard((HWND) window->GetSystemWindow()); if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { HGLOBAL memory = GetClipboardData(CF_UNICODETEXT); clipboardText = (wchar_t *) GlobalLock(memory); GlobalUnlock(memory); } else if (IsClipboardFormatAvailable(CF_TEXT)) { HGLOBAL memory = GetClipboardData(CF_TEXT); clipboardText = (char *) GlobalLock(memory); GlobalUnlock(memory); } CloseClipboard(); return clipboardText; } S::Bool S::GUI::ClipboardWin32::SetClipboardText(const String &text) { if (window == NIL) return False; /* Allocate clipboard memory and copy text. */ HGLOBAL memory = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(wchar_t) * (text.Length() + 1)); memcpy(GlobalLock(memory), (wchar_t *) text, sizeof(wchar_t) * (text.Length() + 1)); GlobalUnlock(memory); /* Pass data to the clipboard. */ OpenClipboard((HWND) window->GetSystemWindow()); EmptyClipboard(); SetClipboardData(CF_UNICODETEXT, memory); CloseClipboard(); return True; } smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/xlib/000077500000000000000000000000001516402577000246505ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/xlib/Makefile000066400000000000000000000011601516402577000263060ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags x11) endif endif endif # Enter object files here: OBJECTS = ifeq ($(BUILD_XLIB),True) OBJECTS += clipboardxlib.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/backends/xlib/clipboardxlib.cpp000066400000000000000000000072361516402577000302020ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include using namespace X11; S::GUI::ClipboardBackend *CreateClipboardXLib(S::GUI::Window *window) { return new S::GUI::ClipboardXLib(window); } S::Int clipboardXLibTmp = S::GUI::ClipboardBackend::SetBackend(&CreateClipboardXLib); S::GUI::ClipboardXLib::ClipboardXLib(Window *iWindow) { type = CLIPBOARD_XLIB; display = Backends::BackendXLib::GetDisplay(); window = iWindow; } S::GUI::ClipboardXLib::~ClipboardXLib() { } unsigned char *S::GUI::ClipboardXLib::QueryAtom(Display *display, X11::Window self, Atom clipboard, Atom atom) const { XConvertSelection(display, clipboard, atom, atom, self, CurrentTime); XFlush(display); /* Wait for SelectionNotify event to be sent. */ XEvent e; do { XNextEvent(display, &e); WindowXLib *backend = GUI::WindowXLib::GetWindowBackend(e.xany.window); if (backend != NIL) backend->ProcessSystemMessages(&e); } while (e.type != SelectionNotify); Atom type; int format; unsigned long items, bytes; unsigned char *data = NIL; /* Do not get any data yet, see how much data is there. */ if (XGetWindowProperty(display, self, atom, 0, 0, 0, AnyPropertyType, &type, &format, &items, &bytes, &data) == 0) { if (data != NIL) { XFree(data); data = NIL; } /* Data is there! */ if (bytes > 0) XGetWindowProperty(display, self, atom, 0, bytes, 0, AnyPropertyType, &type, &format, &items, &bytes, &data); } return data; } S::String S::GUI::ClipboardXLib::GetText(Atom clipboard) const { if (window == NIL) return NIL; String text; X11::Window self = (X11::Window) window->GetSystemWindow(); X11::Window owner = XGetSelectionOwner(display, clipboard); if (owner != None) { unsigned char *data = QueryAtom(display, self, clipboard, XInternAtom(display, "UTF8_STRING", True)); if (data != NIL) { text.ImportFrom("UTF-8", (char *) data); XFree(data); } else { unsigned char *data = QueryAtom(display, self, clipboard, XA_STRING); if (data != NIL) { text = (char *) data; XFree(data); } } } return text; } S::Bool S::GUI::ClipboardXLib::SetText(Atom clipboard, const String &text) { if (window == NIL) return False; X11::Window self = (X11::Window) window->GetSystemWindow(); WindowXLib *backend = GUI::WindowXLib::GetWindowBackend(self); if (backend != NIL) { if (clipboard == XA_PRIMARY) backend->SetSelection(text); else if (clipboard == XInternAtom(display, "CLIPBOARD", True)) backend->SetClipboard(text); } XSetSelectionOwner(display, clipboard, self, CurrentTime); XFlush(display); return True; } S::String S::GUI::ClipboardXLib::GetSelectionText() const { return GetText(XA_PRIMARY); } S::Bool S::GUI::ClipboardXLib::SetSelectionText(const String &text) { return SetText(XA_PRIMARY, text); } S::String S::GUI::ClipboardXLib::GetClipboardText() const { if (display == NIL) return NIL; return GetText(XInternAtom(display, "CLIPBOARD", True)); } S::Bool S::GUI::ClipboardXLib::SetClipboardText(const String &text) { if (display == NIL) return False; return SetText(XInternAtom(display, "CLIPBOARD", True), text); } smooth-0.9.11~git20260403.0230c0da/classes/gui/clipboard/clipboard.cpp000066400000000000000000000021501516402577000246010ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2012 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::GUI::Clipboard::Clipboard(Window *window) { backend = ClipboardBackend::CreateBackendInstance(window); } S::GUI::Clipboard::~Clipboard() { delete backend; } S::String S::GUI::Clipboard::GetSelectionText() const { return backend->GetSelectionText(); } S::Bool S::GUI::Clipboard::SetSelectionText(const String &text) { return backend->SetSelectionText(text); } S::String S::GUI::Clipboard::GetClipboardText() const { return backend->GetClipboardText(); } S::Bool S::GUI::Clipboard::SetClipboardText(const String &text) { return backend->SetClipboardText(text); } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/000077500000000000000000000000001516402577000216235ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/Makefile000066400000000000000000000011561516402577000232660ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = colordlg.o dialog.o fontdlg.o messagebox.o splashscreen.o tipodaydlg.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,directory) ALLCMD2 = $(call makein,file) ALLCMD3 = $(call makein,icons) CLEANCMD1 = $(call cleanin,directory) CLEANCMD2 = $(call cleanin,file) CLEANCMD3 = $(call cleanin,icons) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/colordlg.cpp000077500000000000000000000670501516402577000241470ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2023 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include S::GUI::Dialogs::ColorSelection::ColorSelection() { for (Int y = 0; y < 256; y++) { for (Int x = 0; x < 256; x++) { colortable[x][y] = Color(x, y, 255, Color::HSV).ConvertTo(Color::RGB); } } color = 0; forcehupdate = False; forcevsupdate = False; preventhupdate = False; preventvsupdate = False; updatetext = True; updatehextext = True; acthue = color.ConvertTo(Color::HSV).GetRed(); actsat = color.ConvertTo(Color::HSV).GetGreen(); actval = color.ConvertTo(Color::HSV).GetBlue(); actred = color.GetRed(); actgreen = color.GetGreen(); actblue = color.GetBlue(); dlgwnd = new Window(I18n::Translator::defaultTranslator->TranslateString("Color selection"), Point(100, 100), Size(438, 288)); titlebar = new Titlebar(TB_CLOSEBUTTON); divbar = new Divider(39, OR_HORZ | OR_BOTTOM); okbtn = new Button(I18n::Translator::defaultTranslator->TranslateString("OK"), Point(87, 29), Size()); okbtn->onAction.Connect(&ColorSelection::OnOK, this); okbtn->SetOrientation(OR_LOWERRIGHT); cancelbtn = new Button(I18n::Translator::defaultTranslator->TranslateString("Cancel"), Point(175, 29), Size()); cancelbtn->onAction.Connect(&ColorSelection::OnCancel, this); cancelbtn->SetOrientation(OR_LOWERRIGHT); ncarea = new ActiveArea(Color(), Point(238, 3), Size(91, 23)); ocarea = new ActiveArea(Color(), Point(334, 3), Size(91, 23)); ocarea->onAction.Connect(&ColorSelection::OnSelectOriginalColor, this); hueslider = new Slider(Point(174, 35), Size(129, 0), OR_HORZ, &acthue, 0, 255); hueslider->onValueChange.Connect(&ColorSelection::ColorDlgHueSlider, this); hueslider->SetOrientation(OR_UPPERRIGHT); satslider = new Slider(Point(174, hueslider->GetY() + 26), Size(129, 0), OR_HORZ, &actsat, 0, 255); satslider->onValueChange.Connect(&ColorSelection::ColorDlgSatSlider, this); satslider->SetOrientation(OR_UPPERRIGHT); valslider = new Slider(Point(174, satslider->GetY() + 26), Size(129, 0), OR_HORZ, &actval, 0, 255); valslider->onValueChange.Connect(&ColorSelection::ColorDlgValSlider, this); valslider->SetOrientation(OR_UPPERRIGHT); redslider = new Slider(Point(174, valslider->GetY() + 26), Size(129, 0), OR_HORZ, &actred, 0, 255); redslider->onValueChange.Connect(&ColorSelection::ColorDlgRedSlider, this); redslider->SetOrientation(OR_UPPERRIGHT); greenslider = new Slider(Point(174, redslider->GetY() + 26), Size(129, 0), OR_HORZ, &actgreen, 0, 255); greenslider->onValueChange.Connect(&ColorSelection::ColorDlgGreenSlider, this); greenslider->SetOrientation(OR_UPPERRIGHT); blueslider = new Slider(Point(174, greenslider->GetY() + 26), Size(129, 0), OR_HORZ, &actblue, 0, 255); blueslider->onValueChange.Connect(&ColorSelection::ColorDlgBlueSlider, this); blueslider->SetOrientation(OR_UPPERRIGHT); huetext = new Text(I18n::Translator::defaultTranslator->TranslateString("H"), Point(189, 37)); huetext->SetOrientation(OR_UPPERRIGHT); huetext->SetFont(Font(Font::Default, Font::DefaultSize, Font::Normal, Font::Normal, Setup::TextColor)); sattext = new Text(I18n::Translator::defaultTranslator->TranslateString("S"), Point(189, huetext->GetY() + 26)); sattext->SetOrientation(OR_UPPERRIGHT); sattext->SetFont(Font(Font::Default, Font::DefaultSize, Font::Normal, Font::Normal, Setup::TextColor)); valtext = new Text(I18n::Translator::defaultTranslator->TranslateString("V"), Point(189, sattext->GetY() + 26)); valtext->SetOrientation(OR_UPPERRIGHT); valtext->SetFont(Font(Font::Default, Font::DefaultSize, Font::Normal, Font::Normal, Setup::TextColor)); redtext = new Text(I18n::Translator::defaultTranslator->TranslateString("R"), Point(189, valtext->GetY() + 26)); redtext->SetOrientation(OR_UPPERRIGHT); redtext->SetFont(Font(Font::Default, Font::DefaultSize, Font::Normal, Font::Normal, Color(255, 0, 0))); greentext = new Text(I18n::Translator::defaultTranslator->TranslateString("G"), Point(189, redtext->GetY() + 26)); greentext->SetOrientation(OR_UPPERRIGHT); greentext->SetFont(Font(Font::Default, Font::DefaultSize, Font::Normal, Font::Normal, Color(0, 160, 0))); bluetext = new Text(I18n::Translator::defaultTranslator->TranslateString("B"), Point(189, greentext->GetY() + 26)); bluetext->SetOrientation(OR_UPPERRIGHT); bluetext->SetFont(Font(Font::Default, Font::DefaultSize, Font::Normal, Font::Normal, Color(0, 0, 255))); hextext = new Text(I18n::Translator::defaultTranslator->TranslateString("HTML code"), Point(189, bluetext->GetY() + 26)); hextext->SetOrientation(OR_UPPERRIGHT); hextext->SetFont(Font(Font::Default, Font::DefaultSize, Font::Normal, Font::Normal, Setup::TextColor)); hueedit = new EditBox(String::FromInt(acthue), Point(37, 34), Size(30, 0), 3); hueedit->onInput.Connect(&ColorSelection::ColorDlgHueEdit, this); hueedit->SetFlags(EDB_NUMERIC); hueedit->SetOrientation(OR_UPPERRIGHT); satedit = new EditBox(String::FromInt(actsat), Point(37, hueedit->GetY() + 26), Size(30, 0), 3); satedit->onInput.Connect(&ColorSelection::ColorDlgSatEdit, this); satedit->SetFlags(EDB_NUMERIC); satedit->SetOrientation(OR_UPPERRIGHT); valedit = new EditBox(String::FromInt(actval), Point(37, satedit->GetY() + 26), Size(30, 0), 3); valedit->onInput.Connect(&ColorSelection::ColorDlgValEdit, this); valedit->SetFlags(EDB_NUMERIC); valedit->SetOrientation(OR_UPPERRIGHT); rededit = new EditBox(String::FromInt(actred), Point(37, valedit->GetY() + 26), Size(30, 0), 3); rededit->onInput.Connect(&ColorSelection::ColorDlgRedEdit, this); rededit->SetFlags(EDB_NUMERIC); rededit->SetOrientation(OR_UPPERRIGHT); greenedit = new EditBox(String::FromInt(actgreen), Point(37, rededit->GetY() + 26), Size(30, 0), 3); greenedit->onInput.Connect(&ColorSelection::ColorDlgGreenEdit, this); greenedit->SetFlags(EDB_NUMERIC); greenedit->SetOrientation(OR_UPPERRIGHT); blueedit = new EditBox(String::FromInt(actblue), Point(37, greenedit->GetY() + 26), Size(30, 0), 3); blueedit->onInput.Connect(&ColorSelection::ColorDlgBlueEdit, this); blueedit->SetFlags(EDB_NUMERIC); blueedit->SetOrientation(OR_UPPERRIGHT); ColorDlgUpdateHexValue(); hexedit = new EditBox(hexval, Point(77, blueedit->GetY() + 26), Size(70, 0), 7); hexedit->onInput.Connect(&ColorSelection::ColorDlgHexEdit, this); hexedit->SetOrientation(OR_UPPERRIGHT); huecapt = False; vscapt = False; lasthue = -1; lastsat = -1; lastval = -1; Add(dlgwnd); dlgwnd->Add(okbtn); dlgwnd->Add(cancelbtn); dlgwnd->Add(ncarea); dlgwnd->Add(ocarea); dlgwnd->Add(hueslider); dlgwnd->Add(satslider); dlgwnd->Add(valslider); dlgwnd->Add(redslider); dlgwnd->Add(greenslider); dlgwnd->Add(blueslider); dlgwnd->Add(huetext); dlgwnd->Add(sattext); dlgwnd->Add(valtext); dlgwnd->Add(redtext); dlgwnd->Add(greentext); dlgwnd->Add(bluetext); dlgwnd->Add(hueedit); dlgwnd->Add(satedit); dlgwnd->Add(valedit); dlgwnd->Add(rededit); dlgwnd->Add(greenedit); dlgwnd->Add(blueedit); dlgwnd->Add(hextext); dlgwnd->Add(hexedit); dlgwnd->Add(titlebar); dlgwnd->Add(divbar); dlgwnd->onPaint.Connect(&ColorSelection::ColorDlgPaintProc, this); dlgwnd->onEvent.Connect(&ColorSelection::ColorDlgMessageProc, this); dlgwnd->SetFlags(dlgwnd->GetFlags() | WF_MODAL); xoffset = Math::Round((dlgwnd->GetMainLayer()->GetX() - 1.0) * Surface().GetSurfaceDPI() / 96.0); yoffset = Math::Round((dlgwnd->GetMainLayer()->GetY() - 1.0) * Surface().GetSurfaceDPI() / 96.0); } S::GUI::Dialogs::ColorSelection::~ColorSelection() { DeleteObject(titlebar); DeleteObject(divbar); DeleteObject(dlgwnd); DeleteObject(okbtn); DeleteObject(cancelbtn); DeleteObject(ncarea); DeleteObject(ocarea); DeleteObject(hueslider); DeleteObject(satslider); DeleteObject(valslider); DeleteObject(redslider); DeleteObject(greenslider); DeleteObject(blueslider); DeleteObject(huetext); DeleteObject(sattext); DeleteObject(valtext); DeleteObject(redtext); DeleteObject(greentext); DeleteObject(bluetext); DeleteObject(hueedit); DeleteObject(satedit); DeleteObject(valedit); DeleteObject(rededit); DeleteObject(greenedit); DeleteObject(blueedit); DeleteObject(hextext); DeleteObject(hexedit); } const Error &S::GUI::Dialogs::ColorSelection::ShowDialog() { if (parentWindow != NIL) dlgwnd->SetMetrics(parentWindow->GetPosition() + Point(25, 25), Size(436, 286)); if (caption != NIL) dlgwnd->SetText(caption); ColorDlgUpdatePickers(); dlgwnd->WaitUntilClosed(); return error; } S::Int S::GUI::Dialogs::ColorSelection::SetColor(const Color &newColor) { color = newColor; acthue = color.ConvertTo(Color::HSV).GetRed(); actsat = color.ConvertTo(Color::HSV).GetGreen(); actval = color.ConvertTo(Color::HSV).GetBlue(); actred = color.GetRed(); actgreen = color.GetGreen(); actblue = color.GetBlue(); ColorDlgUpdateHexValue(); hueedit->SetText(String::FromInt(acthue)); satedit->SetText(String::FromInt(actsat)); valedit->SetText(String::FromInt(actval)); rededit->SetText(String::FromInt(actred)); greenedit->SetText(String::FromInt(actgreen)); blueedit->SetText(String::FromInt(actblue)); hexedit->SetText(hexval); return Success(); } const S::GUI::Color &S::GUI::Dialogs::ColorSelection::GetColor() const { return color; } void S::GUI::Dialogs::ColorSelection::ColorDlgPaintProc() { Surface *surface = dlgwnd->GetDrawSurface(); Rect rect; Rect urect = dlgwnd->GetUpdateRect(); Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); Int huexoffset = hssize + Math::Round(14.0 * surface->GetSurfaceDPI() / 96.0); double huebias = 256 / (double) hssize; Bitmap bmp(Size(hssize, hssize)); rect.left = huexoffset; rect.top = yoffset; rect.right = rect.left + Math::Round(16.0 * surface->GetSurfaceDPI() / 96.0) + 2; rect.bottom = rect.top + hssize + 2; if (Rect::DoRectsOverlap(rect, urect)) { double hue = 0; surface->Frame(rect, FRAME_DOWN); for (Int ypos = 0; ypos < hssize; ypos++) { Point p1(huexoffset + 1, yoffset + 1 + ypos); Point p2(huexoffset + Math::Round(16.0 * surface->GetSurfaceDPI() / 96.0) + 1, yoffset + 1 + ypos); surface->Line(p1, p2, Color(255 - Math::Round(hue), 255, 255, Color::HSV).ConvertTo(Color::RGB)); hue += huebias; } } rect.left = xoffset; rect.right = rect.left + hssize + 2; surface->Frame(rect, FRAME_DOWN); rect.left = xoffset - 4; rect.top = yoffset - 4; rect.right = rect.left + hssize; rect.bottom = rect.top + hssize; surface->StartPaint(Rect(Point(xoffset - 4, yoffset - 4), Size(hssize + Math::Round(30.0 * surface->GetSurfaceDPI() / 96.0) + 5, hssize + 5))); forcehupdate = True; preventvsupdate = True; ColorDlgUpdatePickers(); if (Rect::DoRectsOverlap(rect, urect)) { Rect irect = Rect::OverlapRect(rect, urect); irect.right += 5; irect.bottom += 5; Int xmin = irect.left - (xoffset + 1); Int ymin = irect.top - (yoffset + 1); Int xmax = irect.right - (xoffset + 1); Int ymax = irect.bottom - (yoffset + 1); rect.left = xmin; rect.top = ymin; rect.right = xmax; rect.bottom = ymax; for (int sat = Math::Max(0, ymin); sat < Math::Min(hssize, ymax); sat++) { int normrgb = colortable[acthue][255 - Math::Round(sat * (256.0 / hssize))]; double rbias = (double) Color(normrgb).GetRed() / (255.0 / (256.0 / hssize)); double gbias = (double) Color(normrgb).GetGreen() / (255.0 / (256.0 / hssize)); double bbias = (double) Color(normrgb).GetBlue() / (255.0 / (256.0 / hssize)); double ared = -rbias + Math::Max(0, xmin) * rbias; double agreen = -gbias + Math::Max(0, xmin) * gbias; double ablue = -bbias + Math::Max(0, xmin) * bbias; for (int val = Math::Max(0, xmin); val < Math::Min(hssize, xmax); val++) { bmp.SetPixel(Point(val, sat), Color(Math::Round(ared += rbias), Math::Round(agreen += gbias), Math::Round(ablue += bbias))); } } surface->BlitFromBitmap(bmp, rect, irect); } forcevsupdate = True; preventhupdate = True; ColorDlgUpdatePickers(); surface->EndPaint(); ncarea->SetColor(Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB)); } void S::GUI::Dialogs::ColorSelection::ColorDlgMessageProc(Int message, Int wparam, Int lparam) { Surface *surface = dlgwnd->GetDrawSurface(); Rect huerect; Rect vsrect; Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); Int huexoffset = hssize + Math::Round(14.0 * surface->GetSurfaceDPI() / 96.0); huerect.left = huexoffset; huerect.top = yoffset; huerect.right = huerect.left + Math::Round(16.0 * surface->GetSurfaceDPI() / 96.0) + 1; huerect.bottom = huerect.top + hssize + 1; vsrect.left = xoffset + 1; vsrect.top = yoffset + 1; vsrect.right = vsrect.left + hssize; vsrect.bottom = vsrect.top + hssize; switch (message) { case SM_LBUTTONDOWN: if (dlgwnd->IsMouseOn(huerect)) { huecapt = True; ColorDlgMessageProc(SM_MOUSEMOVE, 0, 0); } else if (dlgwnd->IsMouseOn(vsrect)) { vscapt = True; ColorDlgMessageProc(SM_MOUSEMOVE, 0, 0); } break; case SM_LBUTTONUP: if (huecapt) { huecapt = False; dlgwnd->SetUpdateRect(vsrect); ColorDlgPaintProc(); } else if (vscapt) { vscapt = False; } break; case SM_MOUSEMOVE: if (huecapt) { Int newhue = 255 - Math::Round(Math::Max(Math::Min(dlgwnd->GetMousePosition().y - (yoffset + 1), hssize - 1), 0) * (256.0 / hssize)); if (newhue != acthue) { lasthue = acthue; acthue = newhue; dlgwnd->SetUpdateRect(Rect(Point(xoffset + 1, yoffset + 1), Size(hssize, hssize))); ColorDlgPaintProc(); actred = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetRed(); actgreen = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetGreen(); actblue = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetBlue(); ColorDlgUpdateHexValue(); hueedit->SetText(String::FromInt(acthue)); rededit->SetText(String::FromInt(actred)); greenedit->SetText(String::FromInt(actgreen)); blueedit->SetText(String::FromInt(actblue)); hexedit->SetText(hexval); } } else if (vscapt) { Point mousePos = dlgwnd->GetMousePosition(); Int newval = Math::Round(Math::Max(Math::Min(mousePos.x - (xoffset + 1), hssize - 1), 0) * (256.0 / hssize)); Int newsat = 255 - Math::Round(Math::Max(Math::Min(mousePos.y - (yoffset + 1), hssize - 1), 0) * (256.0 / hssize)); if ((newval != actval) || (newsat != actsat)) { lastval = actval; lastsat = actsat; actval = newval; actsat = newsat; ncarea->SetColor(Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB)); surface->StartPaint(Rect(Point(xoffset - 4, yoffset - 4), Size(hssize + 5, hssize + 5))); ColorDlgUpdatePickers(); surface->EndPaint(); actred = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetRed(); actgreen = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetGreen(); actblue = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetBlue(); ColorDlgUpdateHexValue(); valedit->SetText(String::FromInt(actval)); satedit->SetText(String::FromInt(actsat)); rededit->SetText(String::FromInt(actred)); greenedit->SetText(String::FromInt(actgreen)); blueedit->SetText(String::FromInt(actblue)); hexedit->SetText(hexval); } } break; } } void S::GUI::Dialogs::ColorSelection::ColorDlgUpdatePickers() { Surface *surface = dlgwnd->GetDrawSurface(); Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); Int huexoffset = hssize + Math::Round(14.0 * surface->GetSurfaceDPI() / 96.0); if (((lasthue != acthue) || forcehupdate) && !preventhupdate) { /* Update hue picker. */ if (lasthue != -1) { Point p1(huexoffset + 1, yoffset + 1 + (Int) ((255.0 - lasthue) / (256.0 / hssize))); Point p2(huexoffset + Math::Round(16.0 * surface->GetSurfaceDPI() / 96.0) + 1, yoffset + 1 + (Int) ((255.0 - lasthue) / (256.0 / hssize))); surface->Line(p1, p2, Color(lasthue, 255, 255, Color::HSV).ConvertTo(Color::RGB)); } Color ahrgb = Color(acthue, 255, 255, Color::HSV).ConvertTo(Color::RGB); for (Int x = huexoffset + 1; x < (huexoffset + Math::Round(16.0 * surface->GetSurfaceDPI() / 96.0) + 1); x++) { surface->SetPixel(Point(x, yoffset + 1 + (Int) ((255.0 - acthue) / (256.0 / hssize))), Color(255 - ahrgb.GetRed(), 255 - ahrgb.GetGreen(), 255 - ahrgb.GetBlue())); } lasthue = acthue; } if (((lastval != actval) || (lastsat != actsat) || forcevsupdate) && !preventvsupdate) { /* Update val/sat picker. */ surface->StartPaint(Rect(Point(xoffset + 1, yoffset + 1), Size(hssize, hssize))); if ((lastval != -1) && (lastsat != -1)) { for (Int x = 0; x < hssize; x++) { Color rgb = Color(acthue, lastsat, (Int) (x * (256.0 / hssize)), Color::HSV).ConvertTo(Color::RGB); surface->SetPixel(Point(x + xoffset + 1, yoffset + 1 + (Int) ((255.0 - lastsat) / (256.0 / hssize))), rgb); } for (Int y = 0; y < hssize; y++) { Color rgb = Color(acthue, (Int) (255.0 - (y * (256.0 / hssize))), lastval, Color::HSV).ConvertTo(Color::RGB); surface->SetPixel(Point(xoffset + 1 + (Int) (lastval / (256.0 / hssize)), y + yoffset + 1), rgb); } } for (Int x = 0; x < hssize; x++) { Color rgb = Color(acthue, actsat, (Int) (x * (256.0 / hssize)), Color::HSV).ConvertTo(Color::RGB); surface->SetPixel(Point(x + xoffset + 1, yoffset + 1 + (Int) ((255.0 - actsat) / (256.0 / hssize))), Color(255 - Color(rgb).GetRed(), 255 - Color(rgb).GetGreen(), 255 - Color(rgb).GetBlue())); } for (Int y = 0; y < hssize; y++) { Color rgb = Color(acthue, (Int) (255.0 - (y * (256.0 / hssize))), actval, Color::HSV).ConvertTo(Color::RGB); surface->SetPixel(Point(xoffset + 1 + (Int) (actval / (256.0 / hssize)), y + yoffset + 1), Color(255 - Color(rgb).GetRed(), 255 - Color(rgb).GetGreen(), 255 - Color(rgb).GetBlue())); } surface->EndPaint(); lastval = actval; lastsat = actsat; } ncarea->SetColor(Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB)); forcehupdate = False; preventhupdate = False; forcevsupdate = False; preventvsupdate = False; } S::Void S::GUI::Dialogs::ColorSelection::OnOK() { color = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB); dlgwnd->Close(); } S::Void S::GUI::Dialogs::ColorSelection::OnCancel() { dlgwnd->Close(); } S::Void S::GUI::Dialogs::ColorSelection::OnSelectOriginalColor() { Surface *surface = dlgwnd->GetDrawSurface(); Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); Rect vsrect = Rect(Point(xoffset + 1, yoffset + 1), Size(hssize, hssize)); lasthue = acthue; lastsat = actsat; lastval = actval; acthue = color.ConvertTo(Color::HSV).GetRed(); actsat = color.ConvertTo(Color::HSV).GetGreen(); actval = color.ConvertTo(Color::HSV).GetBlue(); actred = color.GetRed(); actgreen = color.GetGreen(); actblue = color.GetBlue(); ColorDlgUpdateHexValue(); hueedit->SetText(String::FromInt(acthue)); satedit->SetText(String::FromInt(actsat)); valedit->SetText(String::FromInt(actval)); rededit->SetText(String::FromInt(actred)); greenedit->SetText(String::FromInt(actgreen)); blueedit->SetText(String::FromInt(actblue)); hexedit->SetText(hexval); dlgwnd->SetUpdateRect(vsrect); ColorDlgPaintProc(); } void S::GUI::Dialogs::ColorSelection::ColorDlgHueSlider() { Surface *surface = dlgwnd->GetDrawSurface(); Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); actred = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetRed(); actgreen = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetGreen(); actblue = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetBlue(); if (updatetext) { hueedit->SetText(String::FromInt(acthue)); rededit->SetText(String::FromInt(actred)); greenedit->SetText(String::FromInt(actgreen)); blueedit->SetText(String::FromInt(actblue)); } if (updatehextext) { ColorDlgUpdateHexValue(); hexedit->SetText(hexval); } updatehextext = True; updatetext = True; dlgwnd->SetUpdateRect(Rect(Point(xoffset + 1, yoffset + 1), Size(hssize, hssize))); ColorDlgPaintProc(); } void S::GUI::Dialogs::ColorSelection::ColorDlgSatSlider() { Surface *surface = dlgwnd->GetDrawSurface(); Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); ColorDlgUpdatePickers(); actred = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetRed(); actgreen = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetGreen(); actblue = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetBlue(); if (updatetext) { satedit->SetText(String::FromInt(actsat)); rededit->SetText(String::FromInt(actred)); greenedit->SetText(String::FromInt(actgreen)); blueedit->SetText(String::FromInt(actblue)); } if (updatehextext) { ColorDlgUpdateHexValue(); hexedit->SetText(hexval); } updatehextext = True; updatetext = True; dlgwnd->SetUpdateRect(Rect(Point(xoffset + 1, yoffset + 1), Size(hssize, hssize))); ColorDlgPaintProc(); } void S::GUI::Dialogs::ColorSelection::ColorDlgValSlider() { Surface *surface = dlgwnd->GetDrawSurface(); Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); ColorDlgUpdatePickers(); actred = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetRed(); actgreen = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetGreen(); actblue = Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetBlue(); if (updatetext) { valedit->SetText(String::FromInt(actval)); rededit->SetText(String::FromInt(actred)); greenedit->SetText(String::FromInt(actgreen)); blueedit->SetText(String::FromInt(actblue)); } if (updatehextext) { ColorDlgUpdateHexValue(); hexedit->SetText(hexval); } updatehextext = True; updatetext = True; dlgwnd->SetUpdateRect(Rect(Point(xoffset + 1, yoffset + 1), Size(hssize, hssize))); ColorDlgPaintProc(); } void S::GUI::Dialogs::ColorSelection::ColorDlgRedSlider() { Surface *surface = dlgwnd->GetDrawSurface(); Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); acthue = Color(actred, actgreen, actblue).ConvertTo(Color::HSV).GetRed(); actsat = Color(actred, actgreen, actblue).ConvertTo(Color::HSV).GetGreen(); actval = Color(actred, actgreen, actblue).ConvertTo(Color::HSV).GetBlue(); if (updatetext) { hueedit->SetText(String::FromInt(acthue)); satedit->SetText(String::FromInt(actsat)); valedit->SetText(String::FromInt(actval)); rededit->SetText(String::FromInt(actred)); } if (updatehextext) { ColorDlgUpdateHexValue(); hexedit->SetText(hexval); } updatehextext = True; updatetext = True; dlgwnd->SetUpdateRect(Rect(Point(xoffset + 1, yoffset + 1), Size(hssize, hssize))); ColorDlgPaintProc(); } void S::GUI::Dialogs::ColorSelection::ColorDlgGreenSlider() { Surface *surface = dlgwnd->GetDrawSurface(); Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); acthue = Color(actred, actgreen, actblue).ConvertTo(Color::HSV).GetRed(); actsat = Color(actred, actgreen, actblue).ConvertTo(Color::HSV).GetGreen(); actval = Color(actred, actgreen, actblue).ConvertTo(Color::HSV).GetBlue(); if (updatetext) { hueedit->SetText(String::FromInt(acthue)); satedit->SetText(String::FromInt(actsat)); valedit->SetText(String::FromInt(actval)); greenedit->SetText(String::FromInt(actgreen)); } if (updatehextext) { ColorDlgUpdateHexValue(); hexedit->SetText(hexval); } updatehextext = True; updatetext = True; dlgwnd->SetUpdateRect(Rect(Point(xoffset + 1, yoffset + 1), Size(hssize, hssize))); ColorDlgPaintProc(); } void S::GUI::Dialogs::ColorSelection::ColorDlgBlueSlider() { Surface *surface = dlgwnd->GetDrawSurface(); Int hssize = Math::Round(205.0 * surface->GetSurfaceDPI() / 96.0); acthue = Color(actred, actgreen, actblue).ConvertTo(Color::HSV).GetRed(); actsat = Color(actred, actgreen, actblue).ConvertTo(Color::HSV).GetGreen(); actval = Color(actred, actgreen, actblue).ConvertTo(Color::HSV).GetBlue(); if (updatetext) { hueedit->SetText(String::FromInt(acthue)); satedit->SetText(String::FromInt(actsat)); valedit->SetText(String::FromInt(actval)); blueedit->SetText(String::FromInt(actblue)); } if (updatehextext) { ColorDlgUpdateHexValue(); hexedit->SetText(hexval); } updatehextext = True; updatetext = True; dlgwnd->SetUpdateRect(Rect(Point(xoffset + 1, yoffset + 1), Size(hssize, hssize))); ColorDlgPaintProc(); } void S::GUI::Dialogs::ColorSelection::ColorDlgHueEdit() { Int newhue = Math::Max(0, Math::Min(255, (Int) hueedit->GetText().ToInt())); if (newhue != acthue) { acthue = newhue; updatetext = False; ColorDlgHueSlider(); } } void S::GUI::Dialogs::ColorSelection::ColorDlgSatEdit() { Int newsat = Math::Max(0, Math::Min(255, (Int) satedit->GetText().ToInt())); if (newsat != actsat) { actsat = newsat; updatetext = False; ColorDlgSatSlider(); } } void S::GUI::Dialogs::ColorSelection::ColorDlgValEdit() { Int newval = Math::Max(0, Math::Min(255, (Int) valedit->GetText().ToInt())); if (newval != actval) { actval = newval; updatetext = False; ColorDlgValSlider(); } } void S::GUI::Dialogs::ColorSelection::ColorDlgRedEdit() { Int newred = Math::Max(0, Math::Min(255, (Int) rededit->GetText().ToInt())); if (newred != Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetRed()) { actred = newred; updatetext = False; ColorDlgRedSlider(); } } void S::GUI::Dialogs::ColorSelection::ColorDlgGreenEdit() { Int newgreen = Math::Max(0, Math::Min(255, (Int) greenedit->GetText().ToInt())); if (newgreen != Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetGreen()) { actgreen = newgreen; updatetext = False; ColorDlgGreenSlider(); } } void S::GUI::Dialogs::ColorSelection::ColorDlgBlueEdit() { Int newblue = Math::Max(0, Math::Min(255, (Int) blueedit->GetText().ToInt())); if (newblue != Color(acthue, actsat, actval, Color::HSV).ConvertTo(Color::RGB).GetBlue()) { actblue = newblue; updatetext = False; ColorDlgBlueSlider(); } } void S::GUI::Dialogs::ColorSelection::ColorDlgUpdateHexValue() { hexval[0] = '#'; hexval[1] = 48 + (actred / 16); hexval[2] = 48 + (actred % 16); hexval[3] = 48 + (actgreen / 16); hexval[4] = 48 + (actgreen % 16); hexval[5] = 48 + (actblue / 16); hexval[6] = 48 + (actblue % 16); for (Int i = 1; i < 7; i++) { if (hexval[i] > 57) hexval[i] = 'a' + (hexval[i] - 58); } hueslider->SetValue(acthue); satslider->SetValue(actsat); valslider->SetValue(actval); redslider->SetValue(actred); greenslider->SetValue(actgreen); blueslider->SetValue(actblue); } void S::GUI::Dialogs::ColorSelection::ColorDlgHexValueChanged() { } void S::GUI::Dialogs::ColorSelection::ColorDlgHexEdit() { } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/dialog.cpp000077500000000000000000000017501516402577000235740ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::GUI::Dialogs::Dialog::Dialog() { parentWindow = NIL; error = Success(); } S::GUI::Dialogs::Dialog::~Dialog() { } S::Int S::GUI::Dialogs::Dialog::SetCaption(const String &newCaption) { caption = newCaption; return Success(); } S::Int S::GUI::Dialogs::Dialog::SetParentWindow(Window *newParent) { parentWindow = newParent; return Success(); } const Error &S::GUI::Dialogs::Dialog::GetErrorStatus() const { return error; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/directory/000077500000000000000000000000001516402577000236275ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/directory/Makefile000066400000000000000000000014201516402577000252640ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags gtk+-x11-3.0) endif endif endif # Enter object files here: OBJECTS = dirdlg.o ifeq ($(BUILD_WIN32),True) OBJECTS += dirdlg_win32.o else ifeq ($(BUILD_OSX),True) OBJECTS += dirdlg_cocoa.o else ifeq ($(BUILD_HAIKU),True) OBJECTS += dirdlg_haiku.o else OBJECTS += dirdlg_gtk.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/directory/dirdlg.cpp000077500000000000000000000016611516402577000256070ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2017 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::GUI::Dialogs::DirSelection::DirSelection() { caption = I18n::Translator::defaultTranslator->TranslateString("Select directory"); directory = NIL; } S::GUI::Dialogs::DirSelection::~DirSelection() { } S::Int S::GUI::Dialogs::DirSelection::SetDirName(const String &nDirectory) { directory = nDirectory; return Success(); } const S::String &S::GUI::Dialogs::DirSelection::GetDirName() const { return directory; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/directory/dirdlg_cocoa.mm000066400000000000000000000070511516402577000265760ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #import #include #include #include #include using namespace smooth; using namespace smooth::GUI; @interface CocoaFolderPanel : NSObject { @private NSInteger response; NSURL *url; Window *parentWindow; } /* CocoaFolderPanel methods. */ + (CocoaFolderPanel *) panel; - (id) init; - (void) dealloc; - (void) setParentWindow: (Window *) window; - (void) runModal; - (void) didEndModalSheet: (NSSavePanel *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo; - (NSInteger) response; - (NSURL *) URL; @end @implementation CocoaFolderPanel + (CocoaFolderPanel *) panel { CocoaFolderPanel *panel = [[[CocoaFolderPanel alloc] init] autorelease]; return panel; } - (id) init { [super init]; response = 0; url = nil; parentWindow = NIL; return self; } - (void) dealloc { if (url != NIL) [url release]; [super dealloc]; } - (void) setParentWindow: (Window *) window { parentWindow = window; } - (void) runModal { /* Create and configure panel. */ NSOpenPanel *panel = [NSOpenPanel openPanel]; [panel setFloatingPanel: YES]; [panel setCanChooseDirectories: true]; [panel setCanChooseFiles: false]; /* Run the panel. */ if (Backends::BackendCocoa::IsOSXVersionAtLeast(10, 15, 0) && !Backends::BackendCocoa::IsOSXVersionAtLeast(12, 0, 0)) { [panel beginSheetForDirectory: nil file: nil modalForWindow: parentWindow != NIL ? (NSWindow *) parentWindow->GetSystemWindow() : [NSApp mainWindow] modalDelegate: self didEndSelector: @selector(didEndModalSheet:returnCode:contextInfo:) contextInfo: nil]; [panel runModal]; } else { response = [panel runModal]; /* On macOS 12 the response can be NSModalResponseStop in some cases regardless of the button clicked. */ if (response == -1000) { if ([panel URL] != nil) response = NSOKButton; else response = NSCancelButton; } } /* Get selected URL. */ url = [[panel URL] retain]; } - (void) didEndModalSheet: (NSSavePanel *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo { response = returnCode; } - (NSInteger) response { return response; } - (NSURL *) URL { return url; } @end const Error &S::GUI::Dialogs::DirSelection::ShowDialog() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; /* Create file chooser dialog */ CocoaFolderPanel *panel = [CocoaFolderPanel panel]; [panel setParentWindow: parentWindow]; if ([NSThread isMainThread]) [panel runModal]; else [panel performSelectorOnMainThread: @selector(runModal) withObject: nil waitUntilDone: YES]; if ([panel response] == NSOKButton) directory.ImportFrom("UTF-8", [[[panel URL] path] UTF8String]); [pool release]; /* Check if we actually have a directory */ if (directory != NIL) { if (!directory.EndsWith(Directory::GetDirectoryDelimiter())) directory.Append(Directory::GetDirectoryDelimiter()); } else { error = Error(); } return error; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/directory/dirdlg_gtk.cpp000077500000000000000000000041701516402577000264520ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2026 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #ifdef GDK_WINDOWING_X11 # include # undef True # undef False # undef Bool # undef Success #endif #include #include const Error &S::GUI::Dialogs::DirSelection::ShowDialog() { /* Create file chooser dialog. */ GtkWidget *dialog = gtk_file_chooser_dialog_new(caption, NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); if (directory != NIL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), directory); /* Make sure dialog gets the focus. */ #ifdef GDK_WINDOWING_X11 gtk_widget_show_all(GTK_WIDGET(dialog)); if (GDK_IS_X11_DISPLAY(gtk_widget_get_display(GTK_WIDGET(dialog)))) { GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(dialog)); gdk_window_set_events(window, GdkEventMask(gdk_window_get_events(window) | GDK_PROPERTY_CHANGE_MASK)); gtk_window_present_with_time(GTK_WINDOW(dialog), gdk_x11_get_server_time(window)); } #endif /* Run dialog and check result. */ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { char *name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); directory.ImportFrom("UTF-8", name); g_free(name); } else { directory = NIL; } gtk_widget_destroy(dialog); /* Wait for GTK to finish pending actions. */ while (gtk_events_pending()) gtk_main_iteration(); /* Check if we actually have a directory. */ if (directory != NIL) { if (!directory.EndsWith(Directory::GetDirectoryDelimiter())) directory.Append(Directory::GetDirectoryDelimiter()); } else { error = Error(); } return error; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/directory/dirdlg_haiku.cpp000066400000000000000000000040511516402577000267610ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2017 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include class HaikuDirectoryDialog : public BLooper { private: S::String &directory; public: HaikuDirectoryDialog(S::String &iDirectory) : directory(iDirectory) { } void MessageReceived(BMessage *message) { switch (message->what) { case B_REFS_RECEIVED: { entry_ref dir; if (message->FindRef("refs", &dir) == B_OK) { BPath path(&dir); directory.ImportFrom("UTF-8", path.Path()); } } PostMessage(B_QUIT_REQUESTED); break; case B_CANCEL: PostMessage(B_QUIT_REQUESTED); break; default: BLooper::MessageReceived(message); break; }; } }; class HaikuDirectoryFilter : public BRefFilter { public: HaikuDirectoryFilter() { } bool Filter(const entry_ref *ref, BNode *node, stat_beos *st, const char *filetype) { if (S::String(ref->name).StartsWith(".")) return false; if (node->IsDirectory()) return true; return false; } }; const Error &S::GUI::Dialogs::DirSelection::ShowDialog() { HaikuDirectoryDialog *dialog = new HaikuDirectoryDialog(directory); HaikuDirectoryFilter filter; BMessenger messenger(dialog); BFilePanel panel(B_OPEN_PANEL, &messenger, NULL, B_DIRECTORY_NODE, False, NULL, &filter, True, True); if (directory != NIL) panel.SetPanelDirectory(directory); panel.Show(); thread_id thread = dialog->Run(); status_t status = B_OK; wait_for_thread(thread, &status); if (directory == NIL) error = Error(); return error; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/directory/dirdlg_win32.cpp000077500000000000000000000035471516402577000266360ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #define MAX_EXT_PATH 32768 int CALLBACK BrowseCallbackProc(HWND, UINT, LPARAM, LPARAM); const Error &S::GUI::Dialogs::DirSelection::ShowDialog() { BROWSEINFO info = { 0 }; wchar_t buffer[MAX_EXT_PATH] = { 0 }; if (parentWindow != NIL) info.hwndOwner = (HWND) parentWindow->GetSystemWindow(); info.pszDisplayName = buffer; info.lpszTitle = String("\n").Append(caption); info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI; info.lpfn = &BrowseCallbackProc; info.lParam = (LPARAM) this; ITEMIDLIST *idlist = SHBrowseForFolder(&info); SHGetPathFromIDList(idlist, buffer); CoTaskMemFree(idlist); directory = NIL; if (buffer[0] == 0) { error = Error(); return error; } directory = Backends::BackendWin32::GetFullPathName(buffer); if (!directory.EndsWith(Directory::GetDirectoryDelimiter())) directory.Append(Directory::GetDirectoryDelimiter()); return error; } int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) { if (uMsg == BFFM_INITIALIZED && ((S::GUI::Dialogs::DirSelection *) lpData)->GetDirName() != NIL) { SendMessage(hwnd, BFFM_SETSELECTION, true, (LPARAM) (wchar_t *) ((S::GUI::Dialogs::DirSelection *) lpData)->GetDirName()); } return 0; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/file/000077500000000000000000000000001516402577000225425ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/file/Makefile000066400000000000000000000014251516402577000242040ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags gtk+-x11-3.0) endif endif endif # Enter object files here: OBJECTS = filedlg.o ifeq ($(BUILD_WIN32),True) OBJECTS += filedlg_win32.o else ifeq ($(BUILD_OSX),True) OBJECTS += filedlg_cocoa.o else ifeq ($(BUILD_HAIKU),True) OBJECTS += filedlg_haiku.o else OBJECTS += filedlg_gtk.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/file/filedlg.cpp000077500000000000000000000031571516402577000246650ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::GUI::Dialogs::FileSelection::FileSelection() { flags = 0; mode = 0; } S::GUI::Dialogs::FileSelection::~FileSelection() { } S::Int S::GUI::Dialogs::FileSelection::AddFilter(const String &name, const String &filter) { filterNames.Add(name); filters.Add(filter); return Success(); } S::Int S::GUI::Dialogs::FileSelection::SetFlags(Short newFlags) { flags |= newFlags; return Success(); } S::Int S::GUI::Dialogs::FileSelection::SetMode(Short newMode) { mode = newMode; return Success(); } S::Int S::GUI::Dialogs::FileSelection::SetInitialPath(const String &newDefPath) { defPath = newDefPath; return Success(); } S::Int S::GUI::Dialogs::FileSelection::SetDefaultExtension(const String &newDefExt) { defExt = newDefExt; return Success(); } S::Int S::GUI::Dialogs::FileSelection::SetFileName(const String &newDefFile) { defFile = newDefFile; return Success(); } const S::String &S::GUI::Dialogs::FileSelection::GetFileName() const { static const String nil; if (files.Length() > 0) return files.GetFirst(); else return nil; } const S::Array &S::GUI::Dialogs::FileSelection::GetFileNames() const { return files; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/file/filedlg_cocoa.mm000066400000000000000000000133401516402577000256500ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #import #include #include #include #include using namespace smooth; using namespace smooth::GUI; using namespace smooth::GUI::Dialogs; @interface CocoaFilePanel : NSObject { @private Short mode; NSInteger response; NSURL *url; NSArray *urls; Window *parentWindow; BOOL multiSelect; const Array *filters; String defaultPath; String defaultFile; } /* CocoaFilePanel methods. */ + (CocoaFilePanel *) panelWithMode: (Short) mode; - (id) init; - (void) dealloc; - (void) setParentWindow: (Window *) window; - (void) setMultiSelect: (BOOL) val; - (void) setFilters: (const Array *) arr; - (void) setDefaultPath: (String) path; - (void) setDefaultFile: (String) file; - (void) runModal; - (void) didEndModalSheet: (NSSavePanel *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo; - (NSInteger) response; - (NSURL *) URL; - (NSArray *) URLs; @end @implementation CocoaFilePanel + (CocoaFilePanel *) panelWithMode: (Short) mode { CocoaFilePanel *panel = [[[CocoaFilePanel alloc] init] autorelease]; panel->mode = mode; return panel; } - (id) init { [super init]; mode = SFM_OPEN; response = 0; url = nil; urls = nil; parentWindow = NIL; multiSelect = false; return self; } - (void) dealloc { if (url != NIL) [url release]; if (urls != NIL) [urls release]; [super dealloc]; } - (void) setParentWindow: (Window *) window { parentWindow = window; } - (void) setMultiSelect: (BOOL) val { multiSelect = val; } - (void) setFilters: (const Array *) arr { filters = arr; } - (void) setDefaultPath: (String) path { defaultPath = path; } - (void) setDefaultFile: (String) file { defaultFile = file; } - (void) runModal { /* Create and configure panel. */ NSSavePanel *panel = nil; if (mode == SFM_OPEN) panel = [NSOpenPanel openPanel]; else if (mode == SFM_SAVE) panel = [NSSavePanel savePanel]; [panel setFloatingPanel: YES]; if (mode == SFM_OPEN) [(NSOpenPanel *) panel setAllowsMultipleSelection: multiSelect]; /* Add file filters. */ NSMutableArray *fileTypes = [NSMutableArray arrayWithCapacity: filters->Length()]; foreach (const String &filter, *filters) { const Array &patterns = filter.Explode(";"); foreach (String pattern, patterns) { if (pattern.FindLast(".") >= 0) pattern = pattern.Tail(pattern.Length() - pattern.FindLast(".") - 1); if (pattern.Trim() != NIL) [fileTypes addObject: [NSString stringWithUTF8String: pattern.Trim()]]; } } [panel setAllowedFileTypes: fileTypes]; /* Run the panel. */ if (Backends::BackendCocoa::IsOSXVersionAtLeast(10, 15, 0) && !Backends::BackendCocoa::IsOSXVersionAtLeast(12, 0, 0)) { [panel beginSheetForDirectory: defaultPath != NIL ? [NSString stringWithUTF8String: defaultPath.ConvertTo("UTF-8")] : nil file: defaultFile != NIL ? [NSString stringWithUTF8String: defaultFile.ConvertTo("UTF-8")] : nil modalForWindow: parentWindow != NIL ? (NSWindow *) parentWindow->GetSystemWindow() : [NSApp mainWindow] modalDelegate: self didEndSelector: @selector(didEndModalSheet:returnCode:contextInfo:) contextInfo: nil]; [panel runModal]; } else { response = [panel runModalForDirectory: defaultPath != NIL ? [NSString stringWithUTF8String: defaultPath.ConvertTo("UTF-8")] : nil file: defaultFile != NIL ? [NSString stringWithUTF8String: defaultFile.ConvertTo("UTF-8")] : nil]; /* On macOS 12 the response can be NSModalResponseStop in some cases regardless of the button clicked. */ if (response == -1000) { if ([panel URL] != nil) response = NSFileHandlingPanelOKButton; else response = NSFileHandlingPanelCancelButton; } } /* Get selected URLs. */ url = [[panel URL] retain]; if (mode == SFM_OPEN) urls = [[(NSOpenPanel *) panel URLs] retain]; } - (void) didEndModalSheet: (NSSavePanel *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo { response = returnCode; } - (NSInteger) response { return response; } - (NSURL *) URL { return url; } - (NSArray *) URLs { return urls; } @end const Error &S::GUI::Dialogs::FileSelection::ShowDialog() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; /* Create file chooser dialog. */ CocoaFilePanel *panel = [CocoaFilePanel panelWithMode: mode]; [panel setParentWindow: parentWindow]; [panel setFilters: &filters]; if (flags & SFD_ALLOWMULTISELECT) [panel setMultiSelect: true]; [panel setDefaultPath: defPath]; [panel setDefaultFile: defFile]; if ([NSThread isMainThread]) [panel runModal]; else [panel performSelectorOnMainThread: @selector(runModal) withObject: nil waitUntilDone: YES]; if ([panel response] == NSFileHandlingPanelOKButton) { if (mode == SFM_OPEN) { for (NSURL *url in [panel URLs]) { String file; file.ImportFrom("UTF-8", [[url path] UTF8String]); files.Add(file); } } else if (mode == SFM_SAVE) { String file; file.ImportFrom("UTF-8", [[[panel URL] path] UTF8String]); files.Add(file); } } [pool release]; if (files.Length() == 0) error = Error(); return error; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/file/filedlg_gtk.cpp000077500000000000000000000076061516402577000255350ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2026 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #ifdef GDK_WINDOWING_X11 # include # undef True # undef False # undef Bool # undef Success #endif #include #include #include #include const Error &S::GUI::Dialogs::FileSelection::ShowDialog() { /* Create file chooser dialog. */ GtkWidget *dialog = NULL; if (mode == SFM_OPEN) { dialog = gtk_file_chooser_dialog_new(caption, NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); if (flags & SFD_ALLOWMULTISELECT) gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), True); } else if (mode == SFM_SAVE) { dialog = gtk_file_chooser_dialog_new(caption, NULL, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); if (flags & SFD_CONFIRMOVERWRITE) gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), True); } if (defPath != NIL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), defPath); if (defFile != NIL) gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), defFile); /* Add file filters. */ for (int i = 0; i < filters.Length(); i++) { GtkFileFilter *filter = gtk_file_filter_new(); const Array &patterns = filters.GetNth(i).Explode(";"); foreach (const String &pattern, patterns) { /* Make patterns case insensitive. */ String converted = pattern.Head( pattern.FindLast(".") + 1); String extension = pattern.Tail(pattern.Length() - pattern.FindLast(".") - 1).ToLower(); for (Int i = 0; i < extension.Length(); i++) { if (extension[i] >= 'a' && extension[i] <= 'z') converted.Append("[").Append(extension.SubString(i, 1)).Append(extension.SubString(i, 1).ToUpper()).Append("]"); else converted.Append(extension.SubString(i, 1)); } gtk_file_filter_add_pattern(filter, converted.Trim()); } gtk_file_filter_set_name(filter, filterNames.GetNth(i)); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); } /* Make sure dialog gets the focus. */ #ifdef GDK_WINDOWING_X11 gtk_widget_show_all(GTK_WIDGET(dialog)); if (GDK_IS_X11_DISPLAY(gtk_widget_get_display(GTK_WIDGET(dialog)))) { GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(dialog)); gdk_window_set_events(window, GdkEventMask(gdk_window_get_events(window) | GDK_PROPERTY_CHANGE_MASK)); gtk_window_present_with_time(GTK_WINDOW(dialog), gdk_x11_get_server_time(window)); } #endif /* Run dialog and check result. */ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { GSList *list = gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(dialog)); GSList *current = list; while (current != NULL) { String file = String((char *) current->data).Replace("file://", NIL); for (Int i = 0; i < file.Length() - 2; i++) { if (file[i] == '%') { file[i] = (Int64) Number::FromHexString(file.SubString(i + 1, 2)); file = file.Head(i + 1).Append(file.Tail(file.Length() - i - 3)); } } file.ImportFrom("UTF-8", file.ConvertTo("ISO-8859-1")); files.Add(file); g_free(current->data); current = current->next; } g_slist_free(list); } else { error = Error(); } gtk_widget_destroy(dialog); /* Wait for GTK to finish pending actions. */ while (gtk_events_pending()) gtk_main_iteration(); return error; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/file/filedlg_haiku.cpp000066400000000000000000000066311516402577000260430ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include class HaikuFileDialog : public BLooper { private: S::Array &files; public: HaikuFileDialog(S::Array &iFiles) : files(iFiles) { } void MessageReceived(BMessage *message) { switch (message->what) { case B_REFS_RECEIVED: for (int i = 0; i >= 0; i++) { entry_ref ref; if (message->FindRef("refs", i, &ref) != B_OK) break; BEntry entry(&ref, true); BPath path; entry.GetPath(&path); S::String file; file.ImportFrom("UTF-8", path.Path()); files.Add(file); } PostMessage(B_QUIT_REQUESTED); break; case B_SAVE_REQUESTED: { entry_ref dir; const char *name = NULL; if (message->FindRef("directory", &dir) != B_OK) break; if (message->FindString("name", &name) != B_OK) break; BPath path(&dir); S::String file(S::String(path.Path()).Append(S::Directory::GetDirectoryDelimiter()).Append(name)); file.ImportFrom("UTF-8", file.ConvertTo("ISO-8859-1")); files.Add(file); } PostMessage(B_QUIT_REQUESTED); break; case B_CANCEL: PostMessage(B_QUIT_REQUESTED); break; default: BLooper::MessageReceived(message); break; }; } }; class HaikuFileFilter : public BRefFilter { private: const S::Array &filterNames; const S::Array &filters; public: HaikuFileFilter(const S::Array &iFilterNames, const S::Array &iFilters) : filterNames(iFilterNames), filters(iFilters) { } bool Filter(const entry_ref *ref, BNode *node, stat_beos *st, const char *filetype) { if (S::String(ref->name).StartsWith(".")) return false; if (node->IsDirectory()) return true; for (int i = 0; i < filters.Length(); i++) { bool admit = false; const S::Array &patterns = filters.GetNth(i).Explode(";"); for (int j = 0; j < patterns.Length(); j++) { const S::String &pattern = patterns.GetNth(j); if (fnmatch(pattern, ref->name, 0) == 0) { admit = true; break; } } if (admit) return true; } return false; } }; const Error &S::GUI::Dialogs::FileSelection::ShowDialog() { HaikuFileDialog *dialog = new HaikuFileDialog(files); HaikuFileFilter filter(filterNames, filters); BMessenger messenger(dialog); BFilePanel panel(mode == SFM_OPEN ? B_OPEN_PANEL : B_SAVE_PANEL, &messenger, NULL, B_FILE_NODE, flags & SFD_ALLOWMULTISELECT, NULL, &filter, True, True); if (mode == SFM_SAVE && defFile != NIL) panel.SetSaveText(defFile); if ( defPath != NIL) panel.SetPanelDirectory(defPath); panel.Show(); thread_id thread = dialog->Run(); status_t status = B_OK; wait_for_thread(thread, &status); if (files.Length() == 0) error = Error(); return error; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/file/filedlg_win32.cpp000077500000000000000000000057411516402577000257100ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #define MAX_EXT_PATH 32768 const Error &S::GUI::Dialogs::FileSelection::ShowDialog() { Bool result = False; /* Get default filter index. */ Int filterIndex = 1; if (defExt != NIL) { foreach (const String &filter, filters) { if (!filter.ToLower().Contains(String("*.").Append(defExt).ToLower())) continue; filterIndex = foreachindex + 1; break; } } /* Configure and display dialog. */ OPENFILENAME ofn = { 0 }; wchar_t filter[MAX_EXT_PATH] = { 0 }; wchar_t buffer[MAX_EXT_PATH] = { 0 }; wcsncpy(buffer, defFile, defFile.Length()); if (parentWindow != NIL) ofn.hwndOwner = (HWND) parentWindow->GetSystemWindow(); ofn.lStructSize = sizeof(OPENFILENAME); ofn.nFilterIndex = filterIndex; ofn.lpstrFile = buffer; ofn.nMaxFile = MAX_EXT_PATH; ofn.lpstrInitialDir = defPath; ofn.lpstrTitle = caption; ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_EXPLORER | flags; ofn.lpstrDefExt = defExt; Int bpos = 0; for (Int i = 0; i < filters.Length(); i++) { for (Int n = 0; n < filterNames.GetNth(i).Length(); n++) filter[bpos++] = filterNames.GetNth(i)[n]; filter[bpos++] = 0; for (Int n = 0; n < filters.GetNth(i).Length(); n++) filter[bpos++] = filters.GetNth(i)[n]; filter[bpos++] = 0; } filter[bpos++] = 0; ofn.lpstrFilter = filter; if (mode == SFM_OPEN) { ofn.Flags |= OFN_FILEMUSTEXIST; result = GetOpenFileName(&ofn); } else if (mode == SFM_SAVE) { result = GetSaveFileName(&ofn); } if (!result) { error = Error(); return error; } /* Extract file names from result buffer. */ Int n; Int pos = 0; String folder; wchar_t name[MAX_EXT_PATH]; for (n = 0; n < MAX_EXT_PATH; n++) { name[pos++] = buffer[n]; if (buffer[n] == 0) { folder = name; break; } } if (flags & SFD_ALLOWMULTISELECT) { n++; pos = 0; for (; n < MAX_EXT_PATH; n++) { name[pos++] = buffer[n]; if (buffer[n] == 0) { String file = String(folder).Append(Directory::GetDirectoryDelimiter()).Append(name); if (file.EndsWith(Directory::GetDirectoryDelimiter())) file[file.Length() - 1] = 0; files.Add(Backends::BackendWin32::GetFullPathName(file)); pos = 0; if (buffer[n + 1] == 0) break; } } } else { files.Add(Backends::BackendWin32::GetFullPathName(folder)); } return error; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/fontdlg.cpp000077500000000000000000000031621516402577000237710ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #define MAKEUNICODESTR(x) L##x #include #include #ifdef __WIN32__ # include # include #endif S::GUI::Dialogs::FontSelection::FontSelection() { } S::GUI::Dialogs::FontSelection::~FontSelection() { } const Error &S::GUI::Dialogs::FontSelection::ShowDialog() { #ifdef __WIN32__ static CHOOSEFONT cf; LOGFONT lf; if (parentWindow != NIL) cf.hwndOwner = (HWND) parentWindow->GetSystemWindow(); else cf.hwndOwner = NIL; cf.lStructSize = sizeof(CHOOSEFONT); cf.lpLogFont = &lf; cf.Flags = CF_SCREENFONTS | CF_SCRIPTSONLY | CF_NOSCRIPTSEL | CF_EFFECTS | CF_NOOEMFONTS | CF_NOVERTFONTS; cf.rgbColors = 0; if (ChooseFont(&cf)) { font.SetName(lf.lfFaceName); font.SetSize(cf.iPointSize); font.SetWeight(lf.lfWeight == FW_BOLD ? Font::Bold : Font::Normal); font.SetStyle((lf.lfItalic ? Font::Italic : Font::Normal) | (lf.lfUnderline ? Font::Underline : Font::Normal) | (lf.lfStrikeOut ? Font::StrikeOut : Font::Normal)); font.SetColor(cf.rgbColors); } else { error = Error(); } #endif return error; } const S::GUI::Font &S::GUI::Dialogs::FontSelection::GetFont() const { return font; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/icons/000077500000000000000000000000001516402577000227365ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/icons/Makefile000066400000000000000000000004501516402577000243750ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. # Enter object files here: OBJECTS = light.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/icons/light.cpp000066400000000000000000001257421516402577000245640ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include const S::UnsignedByte S::Icons::Light[6951] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0xaa, 0x69, 0x71, 0xde, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xe4, 0x02, 0x01, 0x13, 0x04, 0x1e, 0x03, 0x7e, 0x22, 0x7f, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x2e, 0x23, 0x00, 0x00, 0x2e, 0x23, 0x01, 0x78, 0xa5, 0x3f, 0x76, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x1a, 0xb6, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x9b, 0x77, 0x78, 0x5c, 0xd5, 0xb5, 0xc5, 0xaf, 0x7b, 0xc1, 0x36, 0x2e, 0x72, 0xc5, 0xb6, 0xdc, 0x0d, 0x84, 0x12, 0x9a, 0x81, 0x80, 0x43, 0xe8, 0xd5, 0xf4, 0x1a, 0x20, 0xe0, 0x10, 0x87, 0xf0, 0x30, 0xbc, 0x00, 0x09, 0x24, 0x81, 0x40, 0x4c, 0x20, 0x0e, 0x38, 0x21, 0x21, 0x2f, 0x21, 0xa6, 0x17, 0x5b, 0xb2, 0x5c, 0x54, 0x5c, 0x24, 0x4b, 0xb6, 0x2c, 0xab, 0x77, 0xc9, 0xb2, 0xad, 0xde, 0x35, 0xd2, 0xa8, 0x77, 0xcd, 0xc8, 0x65, 0xee, 0xbd, 0xfb, 0xfd, 0xce, 0xb9, 0xd7, 0x09, 0xc9, 0xcb, 0xfb, 0x5e, 0x9e, 0x6c, 0xe3, 0xfc, 0x91, 0xfb, 0x7d, 0xe7, 0x9b, 0x91, 0x66, 0x34, 0x73, 0xf6, 0x3a, 0x6b, 0xaf, 0xbd, 0xf6, 0x39, 0x57, 0x86, 0x71, 0x12, 0x2e, 0xa9, 0x30, 0x06, 0x49, 0x8a, 0x31, 0x58, 0x92, 0x8c, 0x21, 0x3c, 0x0e, 0x95, 0x78, 0x63, 0x98, 0x1d, 0x67, 0x8c, 0xb0, 0xb7, 0x19, 0xa3, 0x24, 0xda, 0x18, 0x2d, 0x3b, 0x8c, 0x31, 0xb2, 0xdd, 0x18, 0xcb, 0xcf, 0xe3, 0xec, 0x28, 0x63, 0x1c, 0xcf, 0xc7, 0xc9, 0x36, 0x3d, 0xc6, 0xaa, 0xd7, 0x6a, 0x3f, 0x33, 0x46, 0x9c, 0x8c, 0x79, 0x9d, 0xf4, 0xcb, 0xac, 0x26, 0xf0, 0x22, 0x46, 0xa6, 0x0e, 0x7e, 0xa8, 0x24, 0x1a, 0xc3, 0x24, 0xd6, 0x18, 0xa9, 0x83, 0x26, 0x60, 0xd9, 0x6a, 0x9c, 0x6e, 0x6f, 0x35, 0x26, 0xf2, 0x18, 0x24, 0x51, 0xc6, 0x14, 0x3b, 0xd2, 0x98, 0xca, 0xe3, 0x34, 0x40, 0x98, 0x26, 0xce, 0xf3, 0x29, 0xfa, 0x35, 0xde, 0xd3, 0xbb, 0xd9, 0x18, 0x97, 0xfa, 0x96, 0x31, 0xe2, 0xc7, 0xf7, 0x18, 0x83, 0x4e, 0x75, 0x5c, 0xff, 0xd4, 0x25, 0x1e, 0x02, 0xcf, 0x20, 0xf0, 0x44, 0x02, 0x8f, 0x33, 0x86, 0xdb, 0x3b, 0x8d, 0x51, 0xac, 0xf0, 0x18, 0x02, 0x1b, 0xcf, 0x08, 0x62, 0xa8, 0x20, 0x67, 0x49, 0x84, 0x31, 0xd7, 0x8e, 0x30, 0x16, 0x30, 0x16, 0xdb, 0xe1, 0xc6, 0x59, 0x12, 0x6e, 0x9c, 0xcd, 0x73, 0x35, 0xce, 0xe2, 0xe7, 0xc5, 0xee, 0x6b, 0x73, 0x01, 0x63, 0x16, 0xa0, 0x4d, 0xb7, 0xa2, 0x8c, 0xa0, 0xea, 0x0f, 0x8c, 0xd3, 0x3e, 0x7c, 0xda, 0x18, 0x7a, 0xaa, 0x63, 0xfc, 0xdf, 0x83, 0x57, 0x2b, 0x9f, 0x0c, 0xdd, 0x77, 0xb3, 0xe2, 0x31, 0xac, 0xf8, 0x76, 0x02, 0xdf, 0x66, 0x4c, 0x20, 0xe0, 0x29, 0x04, 0x33, 0x8b, 0x95, 0x9e, 0x6f, 0x3b, 0x81, 0x7e, 0x9d, 0xc7, 0x4b, 0x18, 0xdf, 0x60, 0x2c, 0xe5, 0xe7, 0xab, 0x78, 0xfc, 0x96, 0x3b, 0xae, 0xd2, 0xbf, 0x53, 0xaf, 0x45, 0xf0, 0x1e, 0xf5, 0x5e, 0x80, 0x01, 0xb0, 0xf9, 0x1a, 0x8c, 0x6d, 0xc6, 0xd4, 0xce, 0x10, 0x63, 0xdc, 0xae, 0xd7, 0x8d, 0xe1, 0xa7, 0x3a, 0xde, 0xbf, 0x0d, 0xbe, 0x98, 0x55, 0xdf, 0x43, 0xf0, 0xb1, 0xc6, 0x70, 0x82, 0x1f, 0x0d, 0xc5, 0x4f, 0xd7, 0x54, 0x66, 0xb5, 0x09, 0x60, 0x11, 0xe3, 0x7c, 0x82, 0xba, 0xcc, 0x0d, 0xf0, 0x7a, 0x2b, 0xdc, 0xb8, 0xd5, 0xda, 0x32, 0xe8, 0x3e, 0x6b, 0xd3, 0xc8, 0xe5, 0xd6, 0xc6, 0x31, 0x2b, 0xcd, 0xb0, 0xb1, 0xcf, 0x5b, 0x6a, 0x6c, 0x1c, 0xfb, 0xb4, 0xfe, 0x1d, 0xaf, 0xf1, 0xbe, 0x5b, 0xd5, 0x7b, 0xdd, 0xbf, 0x51, 0x7f, 0x7b, 0xbe, 0xfa, 0x2c, 0x3e, 0x77, 0x36, 0xe0, 0x4e, 0x09, 0x44, 0x18, 0xe3, 0x8a, 0xd6, 0x1a, 0x23, 0x7e, 0xf7, 0xe4, 0x29, 0x4e, 0x0f, 0xf2, 0x5d, 0x05, 0x3f, 0x94, 0xe0, 0x47, 0x88, 0xa2, 0x3b, 0xb9, 0xcb, 0x6a, 0xcf, 0xd0, 0x34, 0x0e, 0xd7, 0x81, 0xab, 0x95, 0xbe, 0x96, 0xa0, 0x6f, 0xb3, 0x36, 0x8d, 0xfe, 0x9e, 0x19, 0x32, 0xe1, 0xb7, 0x81, 0x2f, 0x8c, 0xd8, 0xc0, 0x3a, 0xa3, 0x34, 0xb0, 0xc1, 0x68, 0x0b, 0x6c, 0x31, 0xfc, 0x66, 0xc4, 0xa8, 0x23, 0x66, 0x84, 0x71, 0x24, 0xb0, 0xd9, 0xf0, 0xeb, 0xdf, 0xad, 0x33, 0x4a, 0x18, 0x31, 0x66, 0xe8, 0xc4, 0x35, 0xfc, 0xcd, 0x13, 0xfc, 0xfd, 0x6d, 0xea, 0x33, 0x5c, 0x66, 0x9c, 0xa7, 0x3e, 0x1b, 0x20, 0x66, 0x00, 0xc4, 0x24, 0xb4, 0x65, 0x4c, 0xf3, 0x06, 0x63, 0xf8, 0xe6, 0xd7, 0x4f, 0x01, 0x10, 0x3a, 0xf8, 0x78, 0x82, 0x87, 0xf2, 0xb6, 0x52, 0xf4, 0x28, 0x63, 0x32, 0x93, 0x9b, 0xed, 0xe6, 0xf2, 0x12, 0xcb, 0x99, 0xf4, 0xed, 0xd6, 0xc6, 0x89, 0x2f, 0x04, 0xd6, 0x05, 0xed, 0x0c, 0x84, 0x1a, 0xed, 0x66, 0xcc, 0x45, 0x62, 0x65, 0x3f, 0x27, 0x76, 0xc5, 0xc7, 0x22, 0x4d, 0x71, 0x22, 0x1d, 0xd9, 0x22, 0xdd, 0x07, 0x44, 0x7a, 0x0a, 0x45, 0x3a, 0xf7, 0xf1, 0xbb, 0xbd, 0xbc, 0xf6, 0xb9, 0x58, 0x59, 0xcf, 0x8a, 0x19, 0x1d, 0x2c, 0xfc, 0x0d, 0x80, 0x8c, 0xda, 0x61, 0x6e, 0x9c, 0xf0, 0x1c, 0x9f, 0xb5, 0xcc, 0x05, 0x62, 0x89, 0xfa, 0x0e, 0x18, 0x36, 0x1b, 0x20, 0x82, 0x00, 0x61, 0x2c, 0xf3, 0x18, 0xe1, 0x8f, 0x33, 0x86, 0xa4, 0x7d, 0xf2, 0x15, 0x01, 0x21, 0xa5, 0xc6, 0x20, 0x7b, 0xaf, 0x16, 0x3b, 0xb5, 0xf2, 0x2a, 0xf8, 0x29, 0x56, 0x84, 0x31, 0x87, 0xc9, 0x9d, 0xcb, 0xb8, 0x92, 0x71, 0x93, 0xb5, 0xf9, 0xb4, 0x15, 0x81, 0x75, 0xb3, 0xa3, 0x03, 0x61, 0xc6, 0x61, 0x2b, 0xf1, 0x56, 0xb1, 0xab, 0xd6, 0x8a, 0x74, 0xa5, 0x89, 0x1c, 0x2a, 0x13, 0x39, 0x52, 0x27, 0x72, 0xd4, 0x2b, 0x12, 0x68, 0x66, 0xb4, 0x8b, 0x98, 0xdd, 0x22, 0xb6, 0x4f, 0x44, 0x0e, 0x33, 0x4c, 0x9e, 0xf3, 0xd8, 0xef, 0x15, 0xbb, 0x2e, 0x52, 0xac, 0x94, 0xfb, 0x25, 0xb0, 0xd1, 0xe8, 0x0f, 0xac, 0x9b, 0xb8, 0x8d, 0xcf, 0x7c, 0xc2, 0x52, 0x9f, 0xad, 0xbe, 0x23, 0xc2, 0x38, 0x17, 0x10, 0xe6, 0x68, 0xe0, 0x77, 0x00, 0xc2, 0x2e, 0xe6, 0x42, 0xe5, 0x39, 0x9a, 0x7d, 0x92, 0x41, 0x90, 0x1a, 0x57, 0xf0, 0x9c, 0xba, 0x3e, 0xd6, 0x76, 0x84, 0x6e, 0xae, 0x4b, 0x79, 0x25, 0x66, 0xcb, 0xcc, 0x0d, 0xd3, 0x7f, 0x15, 0x08, 0x39, 0xa3, 0xc9, 0xda, 0x79, 0x86, 0xd8, 0xa5, 0x6f, 0xb2, 0xba, 0x7b, 0x44, 0x7c, 0xb9, 0x8c, 0x7c, 0x46, 0x81, 0x88, 0xff, 0x20, 0x01, 0x96, 0x00, 0x46, 0x05, 0x31, 0xd7, 0x00, 0x48, 0x3d, 0x80, 0x34, 0x01, 0x46, 0x1b, 0xf1, 0x77, 0x8a, 0x58, 0x7d, 0x00, 0x71, 0x44, 0xf4, 0x65, 0x02, 0x8c, 0x37, 0x56, 0xac, 0x84, 0x6b, 0x24, 0xb0, 0xde, 0x68, 0x30, 0x37, 0x4c, 0x7d, 0xdd, 0x65, 0xc3, 0x55, 0x5a, 0x5f, 0x14, 0xf0, 0x91, 0xc6, 0x64, 0xd2, 0x6f, 0xac, 0x4e, 0xc5, 0x4c, 0xe6, 0x56, 0x73, 0x92, 0x40, 0xf0, 0x1d, 0x24, 0xf8, 0x3c, 0x63, 0xb0, 0xad, 0xca, 0x9c, 0x53, 0xe2, 0x82, 0x6c, 0x67, 0xe5, 0x55, 0xf0, 0x57, 0x33, 0xee, 0x32, 0xd7, 0xcf, 0xf9, 0x2c, 0xb0, 0x29, 0xc8, 0xb4, 0x92, 0x2e, 0x16, 0xdb, 0xf3, 0x3e, 0xab, 0xbe, 0x9b, 0x11, 0x0f, 0xd5, 0xf7, 0x8a, 0xf4, 0xa6, 0x88, 0xf4, 0x65, 0x00, 0x02, 0xd4, 0xf7, 0x03, 0x46, 0x3f, 0xf4, 0x3f, 0x54, 0x0c, 0x08, 0xe5, 0x8c, 0xea, 0x2f, 0x31, 0xa3, 0x85, 0xd1, 0xe1, 0x32, 0xa3, 0x1f, 0x14, 0x2c, 0x5e, 0x6f, 0x16, 0xfb, 0xe0, 0x6a, 0xc5, 0x86, 0xa3, 0xe6, 0xfa, 0xe9, 0x1f, 0xc2, 0x82, 0x3b, 0x2d, 0x07, 0xf0, 0xf3, 0xa8, 0x14, 0xc1, 0x3a, 0x1d, 0x76, 0x18, 0xa7, 0x91, 0x0e, 0xc3, 0x31, 0x5f, 0x43, 0xa4, 0xe5, 0x24, 0x80, 0x20, 0x65, 0x5a, 0xf4, 0x86, 0x21, 0x40, 0xa3, 0xf9, 0xc2, 0x89, 0x3a, 0xe7, 0x1d, 0xda, 0x5f, 0x65, 0xe9, 0xe0, 0xe7, 0x6e, 0x30, 0xc3, 0x27, 0x8b, 0x9d, 0x7c, 0x3e, 0xc1, 0xff, 0x49, 0xa4, 0x3d, 0xdc, 0x19, 0x9d, 0x5b, 0x01, 0x21, 0x9a, 0x5c, 0x27, 0xef, 0x7b, 0x61, 0x43, 0x5f, 0x12, 0x20, 0x90, 0x0e, 0xfe, 0x2c, 0x40, 0xc8, 0x03, 0x04, 0x58, 0x71, 0x08, 0x1d, 0x38, 0x5c, 0x0a, 0x08, 0x95, 0x8c, 0x5a, 0x80, 0x68, 0x60, 0x34, 0xbb, 0xac, 0xe8, 0x72, 0x80, 0xb0, 0xfd, 0x62, 0xd7, 0x6e, 0x12, 0x44, 0x53, 0xcc, 0xf5, 0xd3, 0xbe, 0xe0, 0x7b, 0xef, 0x60, 0x7c, 0x93, 0x79, 0x9c, 0x63, 0xab, 0xaa, 0x13, 0x45, 0xe9, 0xa5, 0x12, 0xe9, 0x72, 0x9c, 0xc3, 0x5c, 0x9b, 0x4e, 0x20, 0x08, 0x7d, 0x95, 0xda, 0xde, 0x0e, 0xc1, 0xe0, 0x8c, 0x54, 0xa5, 0xce, 0x55, 0xfb, 0xb3, 0xdc, 0x9c, 0x5f, 0x66, 0x86, 0xcc, 0xfe, 0xc8, 0x0c, 0x9f, 0x29, 0x76, 0xc2, 0x48, 0xf2, 0xfd, 0x97, 0x22, 0x2d, 0x9f, 0x31, 0x3e, 0x17, 0x69, 0x5b, 0x8f, 0xd8, 0x85, 0x01, 0x02, 0x40, 0x74, 0x47, 0x01, 0xc2, 0x0e, 0x40, 0x88, 0x05, 0x04, 0x58, 0xe1, 0x4b, 0x04, 0x04, 0x58, 0xd1, 0x0f, 0x2b, 0xfa, 0x73, 0x00, 0x01, 0x21, 0x3c, 0x44, 0x7a, 0x1c, 0x2e, 0x71, 0x58, 0x71, 0x44, 0xb1, 0xc2, 0x03, 0x10, 0x8d, 0x00, 0xd1, 0xea, 0x02, 0x41, 0x4a, 0xd4, 0x6f, 0x15, 0x33, 0x1c, 0x10, 0x42, 0xa6, 0xfd, 0x59, 0x97, 0xcc, 0x08, 0xe3, 0x1b, 0xb0, 0xf1, 0x4c, 0xe6, 0x34, 0x9d, 0xb9, 0x8d, 0x93, 0x9d, 0xa4, 0xc2, 0xde, 0x13, 0x9c, 0x0a, 0x5a, 0xf5, 0xe3, 0xf0, 0xf4, 0x98, 0x1c, 0x57, 0xf1, 0xe7, 0xbb, 0xa6, 0xe6, 0x26, 0x73, 0xc3, 0x94, 0x55, 0x81, 0x4d, 0xf3, 0x8f, 0xda, 0xbb, 0x0d, 0xb1, 0xf7, 0x3f, 0x2e, 0xd2, 0xf8, 0x07, 0xc6, 0x7f, 0x89, 0x34, 0xff, 0x59, 0xa4, 0xf5, 0x43, 0x58, 0xf0, 0x29, 0x00, 0xac, 0x83, 0x05, 0x1b, 0x00, 0x60, 0x33, 0x00, 0x44, 0x02, 0xc0, 0x76, 0x00, 0xd8, 0xc9, 0xd8, 0x05, 0x08, 0x09, 0x00, 0x90, 0xcc, 0x48, 0x07, 0x00, 0xd2, 0xe3, 0x90, 0x62, 0xc5, 0x7e, 0x40, 0x28, 0x62, 0x20, 0x9a, 0x87, 0x5d, 0x56, 0x1c, 0x51, 0xac, 0x68, 0xd1, 0x40, 0xd8, 0xd5, 0x5f, 0x08, 0x02, 0x7b, 0xc8, 0x0a, 0x0b, 0x7a, 0x99, 0x39, 0xdc, 0x48, 0x1a, 0x5c, 0x0c, 0x08, 0xf3, 0xb4, 0x1e, 0x44, 0xeb, 0x54, 0x18, 0x26, 0xd9, 0xcc, 0xd9, 0x7b, 0x02, 0x40, 0x68, 0x48, 0x63, 0xf5, 0x53, 0x41, 0x34, 0x46, 0xaf, 0xfe, 0x78, 0xed, 0xee, 0x22, 0x34, 0xf5, 0xaf, 0xb1, 0x36, 0x0f, 0x7f, 0x3c, 0x10, 0xb2, 0xa8, 0xce, 0xda, 0x45, 0xf0, 0x29, 0x8b, 0x44, 0x6a, 0x7e, 0x2e, 0xd2, 0xb0, 0x1a, 0x00, 0xde, 0x06, 0x80, 0x77, 0x00, 0x00, 0x30, 0xda, 0xdf, 0x03, 0x80, 0x0f, 0x00, 0xe0, 0x13, 0x00, 0xf8, 0x02, 0x00, 0x42, 0x01, 0x60, 0x13, 0xc1, 0xc3, 0x0a, 0x1f, 0xe9, 0xe1, 0x27, 0x3d, 0xfc, 0xa4, 0x47, 0x3f, 0xe9, 0xd1, 0x4f, 0x7a, 0xf4, 0xa7, 0x32, 0x32, 0x01, 0x21, 0xd7, 0x4d, 0x0f, 0x58, 0x71, 0x48, 0xb1, 0xe2, 0x98, 0x68, 0x36, 0x68, 0x56, 0xd8, 0xfb, 0x5e, 0x16, 0x7c, 0x45, 0x05, 0x73, 0x78, 0x54, 0x69, 0x90, 0xa8, 0x54, 0x88, 0x30, 0x66, 0x52, 0x99, 0xc6, 0x6b, 0x47, 0xaa, 0x9a, 0xb1, 0xba, 0x13, 0x00, 0x80, 0x1c, 0x34, 0x06, 0x5b, 0xe4, 0x95, 0x0d, 0xb2, 0xae, 0xea, 0x2f, 0x70, 0x1d, 0xda, 0x6d, 0xe4, 0xfd, 0x46, 0x73, 0xc7, 0x54, 0xa8, 0x0f, 0x00, 0xfb, 0xee, 0x10, 0xa9, 0x7b, 0x19, 0x8a, 0x02, 0x82, 0x77, 0x15, 0x00, 0x50, 0x01, 0x5a, 0xdf, 0x02, 0x80, 0xdf, 0x92, 0x06, 0xef, 0x02, 0x00, 0xba, 0xd0, 0x8d, 0x30, 0xf6, 0xe2, 0x03, 0xfa, 0x48, 0x0f, 0x5f, 0x08, 0x83, 0xf4, 0xf0, 0x6f, 0x61, 0x90, 0x1e, 0x7e, 0xd2, 0xc3, 0x4f, 0x7a, 0xf4, 0x23, 0x9c, 0xfd, 0x88, 0x66, 0x7f, 0x8a, 0xc3, 0x8a, 0x7e, 0x58, 0xd1, 0xef, 0x8a, 0x66, 0x7f, 0x91, 0x53, 0x4a, 0x0f, 0xc3, 0x88, 0x9e, 0x7c, 0x31, 0x63, 0x2f, 0x15, 0x73, 0xdd, 0xe4, 0x75, 0xcc, 0xe5, 0x16, 0xc6, 0xa5, 0x9a, 0x99, 0x30, 0x54, 0x0b, 0x22, 0x8c, 0x95, 0x7c, 0x63, 0xf0, 0xf1, 0x03, 0xb0, 0x0f, 0x24, 0xc9, 0x2b, 0xe8, 0x7f, 0x3a, 0x5f, 0x32, 0xd3, 0x52, 0xab, 0x1f, 0xc1, 0xea, 0x6f, 0x1a, 0xf3, 0x54, 0x60, 0xe3, 0x82, 0x6e, 0x3b, 0x61, 0xb0, 0xd8, 0x49, 0x00, 0x50, 0xfa, 0x1d, 0x91, 0x5a, 0x8c, 0x8e, 0xe7, 0x47, 0x62, 0x7b, 0x7f, 0x22, 0x76, 0xd3, 0x2b, 0x00, 0xf0, 0x0b, 0x00, 0x78, 0x03, 0x06, 0xfc, 0x1a, 0x00, 0x7e, 0xc3, 0xa4, 0x7f, 0x0f, 0x00, 0x7f, 0x04, 0x00, 0x7c, 0x81, 0x8f, 0xf4, 0xf0, 0x91, 0x1e, 0x7e, 0xd2, 0xc3, 0x4f, 0x7a, 0xf8, 0x49, 0x0f, 0x7f, 0x04, 0x63, 0x1b, 0x23, 0x86, 0xa1, 0xd2, 0x03, 0x56, 0xf8, 0x61, 0x85, 0xdf, 0x15, 0x4d, 0x3f, 0xac, 0xf0, 0xbb, 0xa5, 0x94, 0xd4, 0xb0, 0x2b, 0xd6, 0x4a, 0x20, 0xc4, 0x68, 0xc3, 0x35, 0xae, 0x70, 0x2b, 0xd1, 0x39, 0xcc, 0x6f, 0x86, 0x6e, 0xb1, 0x63, 0x98, 0xb3, 0xb2, 0xe9, 0xf5, 0xc7, 0xc1, 0x82, 0xc3, 0xaa, 0xee, 0xab, 0xd6, 0x76, 0x3b, 0xdd, 0x5d, 0x94, 0x31, 0xc9, 0xad, 0xf9, 0xaa, 0x59, 0xb9, 0xd9, 0x0c, 0x09, 0x0e, 0x31, 0xa3, 0xa7, 0x88, 0x9d, 0x48, 0xf0, 0xe9, 0x33, 0x44, 0x2a, 0x1e, 0x13, 0xbb, 0xe6, 0x07, 0x00, 0xf0, 0x34, 0x00, 0xfc, 0xa7, 0xd8, 0xcd, 0x2f, 0x88, 0xdd, 0xfa, 0x92, 0xd8, 0xed, 0xb0, 0xa2, 0xf3, 0x35, 0x56, 0x1f, 0x71, 0xec, 0x25, 0x3d, 0xfa, 0xd6, 0x30, 0x48, 0x0f, 0x1f, 0xe9, 0xe1, 0x83, 0x15, 0x7e, 0xd2, 0xc3, 0x4f, 0x7a, 0xf8, 0x61, 0x85, 0x1f, 0x56, 0xf8, 0x37, 0x32, 0xc2, 0x1d, 0x56, 0xf8, 0x60, 0x85, 0x0f, 0x56, 0xf8, 0x94, 0x68, 0xc2, 0x8a, 0x3e, 0xb7, 0x94, 0xf6, 0x65, 0x3b, 0x9e, 0xa2, 0x2b, 0x55, 0xcc, 0xb8, 0x25, 0x54, 0x85, 0x29, 0x9f, 0x28, 0x3d, 0x62, 0x5c, 0x0c, 0x4b, 0xe7, 0x28, 0x5b, 0x0e, 0x0b, 0x46, 0xd9, 0xbb, 0x98, 0x7b, 0xf9, 0x71, 0x00, 0xa0, 0x9b, 0x9d, 0xdd, 0xba, 0xf4, 0x8d, 0x51, 0xfd, 0xbb, 0xdb, 0xc6, 0x2e, 0xb5, 0x36, 0x0f, 0x79, 0x28, 0x10, 0xba, 0xb0, 0xda, 0x4a, 0x18, 0x4e, 0xd9, 0x33, 0x44, 0xb2, 0x17, 0x88, 0x5d, 0xf9, 0x10, 0x00, 0x7c, 0x07, 0x00, 0xbe, 0x0b, 0x00, 0xdf, 0x07, 0x80, 0xff, 0x00, 0x80, 0x67, 0xc5, 0xee, 0x78, 0x5e, 0xec, 0xae, 0x17, 0xc5, 0xee, 0xf9, 0x99, 0xd8, 0xbd, 0xa4, 0x47, 0x1f, 0xe9, 0xe1, 0x23, 0x3d, 0x7c, 0xb0, 0xc2, 0x0f, 0x2b, 0xfc, 0xb0, 0xc2, 0x0f, 0x2b, 0xfc, 0xb0, 0xc2, 0xff, 0x11, 0x83, 0x0a, 0xe2, 0xa7, 0x7a, 0xf8, 0x60, 0x85, 0x0f, 0x56, 0xf4, 0xc1, 0x8a, 0x3e, 0x58, 0xd1, 0x0b, 0x2b, 0x7a, 0x77, 0x39, 0xa5, 0xb4, 0x17, 0x56, 0xf4, 0xc2, 0x8a, 0xbe, 0x1c, 0xb1, 0x0b, 0x5e, 0x12, 0xfa, 0x87, 0x32, 0x6b, 0xcb, 0xe0, 0xfb, 0xdd, 0xaa, 0xb4, 0x48, 0xa7, 0xea, 0x36, 0xd2, 0x40, 0xcd, 0x7d, 0xff, 0x71, 0xa4, 0x81, 0xca, 0x21, 0x4a, 0xdf, 0x70, 0x5d, 0x5e, 0x22, 0x8d, 0x33, 0x5c, 0xf1, 0xbb, 0xd6, 0x0c, 0x0b, 0xfa, 0xa9, 0x19, 0x39, 0xc7, 0xb4, 0x93, 0xa0, 0x7f, 0x2a, 0x00, 0xe4, 0x2e, 0x84, 0x8e, 0x77, 0x01, 0xc0, 0x7d, 0x00, 0x00, 0x10, 0xde, 0x47, 0x01, 0x60, 0xb9, 0xd8, 0x6d, 0x2b, 0x00, 0x00, 0x20, 0xba, 0x9e, 0x01, 0x80, 0x1f, 0x02, 0x00, 0xe9, 0xd1, 0x07, 0x2b, 0x7c, 0xb0, 0xc2, 0x0f, 0x2b, 0xfc, 0xb0, 0xc2, 0xff, 0x2b, 0x72, 0x1b, 0xd1, 0xf4, 0xc3, 0x0a, 0x3f, 0xac, 0xf0, 0xbf, 0xe7, 0xb0, 0xc2, 0x07, 0x2b, 0x7c, 0x88, 0x66, 0x1f, 0xa2, 0xd9, 0x0b, 0x2b, 0x7a, 0x61, 0x45, 0x0f, 0xac, 0xe8, 0x86, 0x15, 0xdd, 0xb0, 0xa2, 0x1b, 0x56, 0xf4, 0xa4, 0xe0, 0x0d, 0x3e, 0x90, 0xc0, 0x26, 0x0c, 0xd2, 0xc6, 0x09, 0x2f, 0x30, 0xbf, 0xab, 0x6d, 0x47, 0x0c, 0x67, 0xe8, 0x5d, 0x26, 0xd5, 0xa5, 0xe2, 0x09, 0x0e, 0x97, 0x0d, 0x80, 0x05, 0xbe, 0x3c, 0xbd, 0xbb, 0xa3, 0xf2, 0x7f, 0x24, 0xf4, 0x57, 0x1b, 0x1b, 0xaa, 0xd9, 0xb9, 0x10, 0xd3, 0x73, 0x63, 0x20, 0x64, 0xf6, 0xa7, 0xe6, 0x4e, 0xc4, 0x2f, 0x65, 0x88, 0x48, 0x3a, 0x20, 0xe4, 0x05, 0x03, 0xc0, 0x4d, 0x00, 0x70, 0x1b, 0x00, 0xdc, 0x09, 0x00, 0xf7, 0x02, 0xc0, 0x83, 0xd0, 0xff, 0x11, 0xb1, 0x3b, 0x1f, 0x17, 0xbb, 0xfb, 0x09, 0x00, 0x78, 0x92, 0xe0, 0x01, 0xc3, 0x07, 0x2b, 0xfc, 0x68, 0x85, 0xff, 0xc7, 0xf8, 0x9b, 0x9f, 0x12, 0x3c, 0xac, 0xe8, 0x87, 0x15, 0xfd, 0xb0, 0xc2, 0x8f, 0x68, 0xfa, 0x11, 0x4d, 0xdf, 0xef, 0x9d, 0xf4, 0xe8, 0x73, 0x45, 0xb3, 0x07, 0x56, 0x74, 0xc3, 0x8a, 0x6e, 0x58, 0xd1, 0x05, 0x2b, 0x3a, 0x29, 0xa5, 0x9d, 0xb0, 0xa2, 0x33, 0x56, 0xec, 0xc6, 0x30, 0x9a, 0xa7, 0x19, 0xf8, 0x82, 0x19, 0x6b, 0x59, 0x9c, 0x1b, 0x98, 0xdf, 0x05, 0xaa, 0x52, 0x91, 0x06, 0xe3, 0xb5, 0x3d, 0x4e, 0xc3, 0xbf, 0x54, 0x0d, 0x00, 0x80, 0x40, 0xb1, 0xce, 0xff, 0x21, 0x76, 0x8c, 0xce, 0xff, 0x89, 0xe2, 0xe4, 0xff, 0x12, 0xad, 0xfe, 0x21, 0xf3, 0x13, 0xac, 0x3d, 0xe3, 0x58, 0xfd, 0xe1, 0x22, 0x99, 0x43, 0xc5, 0xce, 0x47, 0x0b, 0x2a, 0x96, 0x02, 0xc0, 0xb5, 0x00, 0x70, 0x23, 0x93, 0xa2, 0x01, 0x6a, 0x01, 0x88, 0xf6, 0x7b, 0x00, 0xe0, 0x7e, 0x00, 0x80, 0x15, 0xbd, 0xb0, 0xa2, 0x0f, 0x30, 0xfc, 0xdf, 0x23, 0xf0, 0x27, 0x09, 0xf8, 0x69, 0x14, 0xfd, 0x59, 0x06, 0x29, 0x72, 0x88, 0x14, 0xe9, 0x87, 0x15, 0xfd, 0x2e, 0x2b, 0x7c, 0x68, 0x85, 0x8f, 0xf4, 0xe8, 0x53, 0xa2, 0x89, 0xa7, 0xe8, 0xc1, 0x53, 0x74, 0x23, 0x9a, 0x9d, 0xb0, 0xa2, 0x13, 0x56, 0x74, 0xc0, 0x8a, 0x76, 0x58, 0xd1, 0x1e, 0x01, 0xd0, 0x61, 0x62, 0xed, 0xb9, 0x80, 0x5e, 0x61, 0x66, 0x9c, 0xbb, 0x97, 0xa0, 0x34, 0xca, 0xd1, 0x81, 0x63, 0xe5, 0x70, 0x20, 0xa6, 0xc8, 0x86, 0x36, 0xb6, 0xda, 0xe2, 0x8a, 0xd6, 0xd6, 0x37, 0xc8, 0xdd, 0xd9, 0xb9, 0x9c, 0x71, 0x4f, 0x60, 0xc3, 0x82, 0x42, 0x2b, 0x09, 0xd7, 0x97, 0x31, 0x86, 0xfc, 0x47, 0x07, 0xf2, 0x4f, 0x13, 0xbb, 0xec, 0x42, 0x00, 0xf8, 0x06, 0x00, 0x7c, 0x13, 0x00, 0xae, 0x21, 0xff, 0x6f, 0x00, 0x80, 0x5b, 0x00, 0x60, 0x19, 0x00, 0x00, 0x46, 0x2f, 0x60, 0xf8, 0xee, 0x27, 0xc0, 0x6f, 0x13, 0xf4, 0xa3, 0x8c, 0xe5, 0x28, 0xf9, 0x0a, 0xc6, 0x53, 0x3c, 0x7f, 0x86, 0x01, 0x2b, 0xfa, 0x61, 0x85, 0x1f, 0x56, 0xf8, 0x5e, 0x25, 0xf8, 0xd7, 0x09, 0x9e, 0xf4, 0xe8, 0x21, 0x3d, 0xba, 0x49, 0x8f, 0x4e, 0x4a, 0x69, 0x87, 0xb2, 0xd8, 0xb0, 0xa2, 0x0d, 0xad, 0x68, 0x85, 0x15, 0xad, 0xeb, 0xa9, 0x36, 0xb4, 0xd0, 0x49, 0x97, 0x02, 0xc0, 0xac, 0x7d, 0xf6, 0x16, 0xe3, 0x2e, 0x5d, 0xa2, 0x29, 0x87, 0x56, 0xa4, 0x31, 0x09, 0x00, 0x46, 0x89, 0xea, 0x5c, 0x4b, 0x07, 0x00, 0x80, 0x94, 0xc0, 0x00, 0xb5, 0xe1, 0xb1, 0x43, 0x03, 0x30, 0x99, 0x14, 0x58, 0xc8, 0x87, 0x5f, 0x61, 0x6d, 0x1e, 0xfa, 0x10, 0xe5, 0xaf, 0xd6, 0x4e, 0x19, 0x49, 0xf0, 0x78, 0xff, 0x9c, 0x51, 0x78, 0x80, 0x61, 0x94, 0x41, 0x74, 0xa0, 0xe6, 0x02, 0xb1, 0xeb, 0x2f, 0x01, 0x80, 0xcb, 0x01, 0x00, 0x46, 0xb4, 0x7f, 0x8b, 0xfc, 0x87, 0x15, 0x3d, 0x80, 0xd1, 0x77, 0x33, 0xc1, 0xdf, 0xc6, 0x2a, 0xdf, 0x49, 0xd0, 0xf7, 0x60, 0x68, 0x1e, 0x60, 0x3c, 0xcc, 0x78, 0x8c, 0x9f, 0x9f, 0x00, 0x00, 0x52, 0xa4, 0x7f, 0x25, 0x00, 0xa0, 0x15, 0x3e, 0xa5, 0x15, 0x3f, 0x75, 0x44, 0xb3, 0x87, 0xf4, 0xe8, 0x22, 0x3d, 0x3a, 0x94, 0xa7, 0x80, 0x15, 0x6d, 0xbf, 0x23, 0x70, 0xe5, 0x34, 0xd1, 0x8a, 0xe6, 0x0f, 0x49, 0xb7, 0x3f, 0x03, 0xc0, 0xf9, 0x94, 0xc3, 0xe0, 0x4a, 0x57, 0x08, 0xd5, 0xe6, 0xc9, 0x02, 0x4b, 0xed, 0x45, 0xee, 0x64, 0xee, 0x6a, 0x11, 0x2b, 0x07, 0x02, 0x00, 0xa8, 0xe9, 0x4d, 0x8f, 0x6d, 0xda, 0x00, 0x4d, 0xd6, 0x5b, 0x5c, 0xa8, 0xac, 0xb5, 0x79, 0xd8, 0x23, 0x58, 0x5f, 0xaf, 0x9d, 0xc6, 0xea, 0xe7, 0xcd, 0x66, 0xf5, 0x27, 0xa0, 0xc4, 0x00, 0x50, 0x42, 0x1a, 0x54, 0x9f, 0x09, 0x03, 0xce, 0x61, 0x55, 0xbe, 0x0e, 0x00, 0x17, 0x01, 0xc0, 0x12, 0x56, 0x1f, 0x30, 0x7a, 0xaf, 0x24, 0xf8, 0x6f, 0x11, 0xfc, 0xb5, 0x04, 0x7a, 0x03, 0x41, 0x03, 0xc6, 0xd1, 0x65, 0x0c, 0xc0, 0x38, 0x7a, 0x1f, 0x3f, 0x3f, 0x04, 0x08, 0xb0, 0xa2, 0x9f, 0x0a, 0xe2, 0xa7, 0x82, 0xf8, 0x28, 0xa5, 0xbd, 0x94, 0xd2, 0x1e, 0x80, 0xe8, 0xc6, 0x53, 0x74, 0xe2, 0x29, 0xda, 0x49, 0x8f, 0x36, 0xd5, 0x67, 0xc0, 0x8a, 0x66, 0x58, 0xd1, 0xf4, 0x5b, 0x6d, 0xbb, 0xed, 0xda, 0xb7, 0x69, 0x97, 0x67, 0x48, 0x20, 0x74, 0x6e, 0x9d, 0x5a, 0x1c, 0xb5, 0x48, 0xcc, 0x75, 0xa1, 0x5e, 0x34, 0xd5, 0x1c, 0x29, 0x06, 0x94, 0x0c, 0x04, 0x00, 0xa5, 0x01, 0x71, 0xfc, 0xf1, 0x56, 0x87, 0x01, 0x7f, 0x05, 0x60, 0xe8, 0xc3, 0x00, 0x50, 0x6f, 0x67, 0x4c, 0x14, 0x29, 0x58, 0x8c, 0xff, 0x9f, 0x25, 0xf6, 0x01, 0xd2, 0xa0, 0x78, 0x34, 0x8d, 0x10, 0xcf, 0x3d, 0xf3, 0x01, 0x80, 0xdf, 0xb7, 0x9d, 0x2d, 0x52, 0xf5, 0x35, 0xde, 0x73, 0x0e, 0x93, 0xbd, 0x90, 0x71, 0x09, 0xc1, 0x5f, 0x4e, 0xc0, 0x80, 0x11, 0xb8, 0x8a, 0x71, 0x0d, 0xbe, 0x1e, 0x30, 0x02, 0xb7, 0x00, 0x00, 0x2e, 0xf2, 0xf0, 0xbd, 0x00, 0x80, 0x70, 0xfa, 0x95, 0x56, 0x00, 0x44, 0x2f, 0x40, 0x74, 0xab, 0x0a, 0x02, 0x10, 0x1d, 0x78, 0x8a, 0x36, 0x74, 0xa2, 0x85, 0x52, 0xda, 0x0c, 0x2b, 0x1a, 0x31, 0x58, 0x5e, 0x0c, 0x56, 0xc3, 0x5b, 0x62, 0x97, 0xff, 0x58, 0xac, 0x78, 0x43, 0x02, 0x1b, 0xe6, 0xd7, 0x58, 0x5b, 0x86, 0x3c, 0xf8, 0x25, 0x00, 0x82, 0xf4, 0x3e, 0x65, 0x82, 0x31, 0xd4, 0x1e, 0x48, 0x15, 0x50, 0x07, 0x1c, 0xb6, 0xb3, 0xed, 0x35, 0xda, 0x52, 0x00, 0x1c, 0x4b, 0x81, 0x2d, 0x83, 0x1e, 0x08, 0x84, 0xcd, 0x2f, 0xb7, 0x33, 0xa7, 0x8b, 0x1c, 0xa0, 0xf5, 0x2d, 0x3a, 0x5b, 0xec, 0xc2, 0xd3, 0x61, 0xc0, 0x08, 0xbc, 0xc0, 0x78, 0x00, 0x98, 0x41, 0x0a, 0xc0, 0x8c, 0xb6, 0xb9, 0x04, 0x1f, 0x2c, 0x92, 0x3f, 0x0f, 0x7b, 0xbc, 0x18, 0x30, 0x00, 0xa4, 0xe1, 0x3c, 0xe8, 0x7c, 0x01, 0x40, 0x00, 0x86, 0x0d, 0x18, 0x36, 0x60, 0x98, 0x57, 0x03, 0x0a, 0x40, 0x1c, 0x06, 0x88, 0xfe, 0x3b, 0x58, 0x7d, 0xb4, 0xa2, 0x0f, 0x20, 0x7a, 0x00, 0xa2, 0x8b, 0x52, 0xda, 0x09, 0x10, 0xed, 0xca, 0x53, 0x50, 0x4a, 0x9b, 0x49, 0x8f, 0x46, 0xc0, 0x68, 0xa0, 0x94, 0x7a, 0x10, 0x4d, 0xcf, 0x2a, 0xd2, 0xef, 0x7e, 0x51, 0xbd, 0x48, 0x20, 0x74, 0x41, 0x91, 0xb5, 0xc5, 0xb8, 0x47, 0xeb, 0x94, 0xda, 0x3b, 0xdc, 0xaa, 0xb7, 0xcc, 0x46, 0x2b, 0x16, 0xdb, 0xc5, 0x03, 0x01, 0x80, 0xbc, 0xb1, 0x1c, 0x0d, 0x18, 0x85, 0x0f, 0x98, 0xf4, 0x17, 0x11, 0xdc, 0x62, 0xdc, 0x1d, 0x08, 0x9d, 0x97, 0x69, 0x67, 0x10, 0x5c, 0x11, 0x14, 0x2f, 0xbd, 0x98, 0xe0, 0x31, 0x42, 0x25, 0x54, 0x83, 0x4a, 0x58, 0x50, 0x07, 0x08, 0x8d, 0x41, 0x4c, 0x78, 0x2a, 0x15, 0x62, 0x32, 0x0e, 0x11, 0x40, 0xfc, 0x73, 0x10, 0x36, 0x80, 0xf0, 0x2c, 0x60, 0xe5, 0xce, 0x14, 0xa9, 0x84, 0x19, 0x87, 0x00, 0xa3, 0x1f, 0x66, 0x04, 0x2e, 0x73, 0x58, 0x71, 0x18, 0x20, 0xfc, 0x4a, 0x2b, 0x10, 0xce, 0x5e, 0x80, 0xe8, 0x56, 0x15, 0x04, 0x20, 0x3a, 0x00, 0xa2, 0x95, 0xea, 0xd1, 0x4c, 0x29, 0x6d, 0x44, 0x27, 0x1a, 0x00, 0xc3, 0x43, 0xf5, 0xa8, 0xa5, 0x7a, 0x54, 0x21, 0x9c, 0xa9, 0x8b, 0xc5, 0x8a, 0x1b, 0x8a, 0x06, 0xcc, 0x4f, 0x01, 0x80, 0xdb, 0x75, 0x4f, 0x40, 0x67, 0xa8, 0xab, 0xc0, 0x4e, 0x44, 0x30, 0xc1, 0x18, 0x12, 0x38, 0x38, 0x90, 0x2a, 0xa0, 0xf6, 0x00, 0xf8, 0x63, 0x9a, 0xa0, 0x51, 0xee, 0x06, 0xc8, 0x5c, 0xfd, 0xe1, 0x4e, 0xff, 0x1f, 0x69, 0xa7, 0x2d, 0x14, 0x29, 0x41, 0xe8, 0xca, 0x50, 0xfe, 0x4a, 0x80, 0x28, 0x43, 0x10, 0x2b, 0x49, 0x85, 0x3a, 0x40, 0xf0, 0x8e, 0x61, 0xc2, 0xe3, 0x44, 0x92, 0x4e, 0x63, 0xa2, 0xa4, 0x4a, 0xef, 0x14, 0x00, 0x80, 0x31, 0x87, 0x67, 0xb2, 0xe2, 0x00, 0xd7, 0x03, 0x18, 0x75, 0xfc, 0xbd, 0xe7, 0x2c, 0x1e, 0xcf, 0x05, 0x0c, 0x80, 0xe8, 0xb9, 0x14, 0x00, 0xf8, 0xbc, 0xbe, 0xab, 0x1d, 0xd1, 0xec, 0xa2, 0x94, 0x76, 0x00, 0x44, 0x1b, 0x9e, 0xa2, 0xe5, 0x01, 0x82, 0xff, 0x36, 0xc1, 0x2b, 0xa7, 0x09, 0x2b, 0x6a, 0xa9, 0x1e, 0x35, 0x00, 0x71, 0x80, 0xd7, 0xf7, 0x1a, 0x62, 0xc5, 0x4c, 0xc6, 0x07, 0x04, 0x87, 0x5a, 0x8e, 0x1d, 0xbe, 0x08, 0xc1, 0x0e, 0x06, 0x80, 0x09, 0xca, 0xc3, 0xa8, 0x2d, 0x3c, 0x7f, 0xde, 0x00, 0x00, 0xb0, 0x2a, 0xdd, 0xfd, 0x3f, 0xf5, 0x21, 0x51, 0xc6, 0x04, 0x50, 0x0d, 0xd6, 0x5e, 0x9b, 0x5a, 0x6b, 0x86, 0x4c, 0x7f, 0xcf, 0x4a, 0x64, 0xf2, 0x65, 0xd7, 0x51, 0xff, 0x29, 0x79, 0x55, 0xa8, 0x7d, 0x35, 0x4c, 0xa8, 0xa4, 0x34, 0xd6, 0x51, 0x15, 0xbc, 0x80, 0xd0, 0x48, 0x95, 0xd8, 0x3d, 0x18, 0xda, 0xf3, 0x73, 0xcf, 0x58, 0xca, 0xda, 0x78, 0x56, 0x7c, 0x12, 0x20, 0x00, 0x46, 0x00, 0x30, 0xcc, 0x59, 0x22, 0x16, 0x69, 0xe2, 0x05, 0x88, 0x0a, 0x58, 0x51, 0x86, 0x56, 0x34, 0x52, 0x4a, 0xfb, 0x2e, 0x23, 0xf8, 0x2b, 0x09, 0x9e, 0xcf, 0x6d, 0x07, 0x88, 0x56, 0x18, 0xd1, 0x44, 0x29, 0x6d, 0xc0, 0x69, 0x7a, 0x00, 0xa3, 0x16, 0x30, 0xaa, 0x1f, 0xe1, 0xfd, 0x3c, 0xa6, 0x4d, 0xd1, 0x00, 0x98, 0x91, 0xb3, 0xc5, 0xdd, 0x2f, 0xbc, 0x4e, 0x6d, 0x9f, 0x03, 0x80, 0x6a, 0x8b, 0x4f, 0xd7, 0x9b, 0xa5, 0x79, 0x03, 0xb4, 0xc2, 0x87, 0x4b, 0xdc, 0x73, 0x3e, 0xdc, 0x14, 0x46, 0xe8, 0x74, 0xf7, 0xb0, 0x43, 0x9d, 0xd8, 0xdc, 0x64, 0x6e, 0x98, 0xf0, 0x9a, 0x19, 0x77, 0x96, 0x25, 0xe5, 0x4c, 0xae, 0x92, 0x51, 0x83, 0xf9, 0xa9, 0xbb, 0x9e, 0x81, 0xfa, 0xd7, 0xe2, 0x0c, 0xbd, 0xa3, 0x58, 0x5d, 0x00, 0x20, 0x37, 0xa5, 0x09, 0x56, 0x74, 0x61, 0x98, 0x7a, 0x46, 0xc0, 0x82, 0xd1, 0x80, 0x00, 0x18, 0x87, 0x00, 0xe3, 0x70, 0x10, 0x63, 0x1a, 0xcf, 0x01, 0xc2, 0x0f, 0x10, 0xbd, 0x00, 0x51, 0x88, 0x56, 0xec, 0xff, 0x1a, 0xc1, 0x03, 0x66, 0xfb, 0x65, 0x4e, 0x29, 0x6d, 0x82, 0x11, 0x5e, 0x80, 0xf6, 0x28, 0xa7, 0xa9, 0x76, 0x98, 0x59, 0xf5, 0x72, 0xaa, 0x47, 0xce, 0x22, 0xdd, 0x85, 0x5a, 0x09, 0xd0, 0x3f, 0x6c, 0x41, 0x8b, 0xb5, 0x79, 0xc4, 0xe3, 0xee, 0x66, 0xe9, 0x59, 0x2c, 0xd6, 0x34, 0x7b, 0x07, 0xfd, 0x8b, 0x6a, 0x89, 0x0b, 0x8f, 0xa7, 0x17, 0xc8, 0xd6, 0x00, 0x0c, 0xd7, 0x27, 0xb9, 0xce, 0x36, 0xd8, 0xb9, 0xfa, 0x84, 0x67, 0xe3, 0xa8, 0x95, 0xe6, 0xd6, 0x45, 0xdd, 0x52, 0xce, 0xca, 0x54, 0xdd, 0x4d, 0xd0, 0xb7, 0x33, 0x41, 0x6c, 0xb0, 0xf7, 0x66, 0x56, 0x0a, 0x61, 0x6c, 0x18, 0x84, 0xe8, 0x11, 0xf4, 0xee, 0x41, 0x04, 0x81, 0x38, 0x76, 0xf2, 0xbc, 0x7b, 0x18, 0x41, 0x32, 0x7c, 0x0c, 0x3f, 0xe0, 0xf8, 0x49, 0x0f, 0x3f, 0x40, 0xf8, 0x00, 0xa2, 0x6f, 0x3a, 0x39, 0x0f, 0x10, 0xe9, 0x8c, 0x42, 0xaa, 0x48, 0x3b, 0x20, 0xb4, 0x02, 0x66, 0x33, 0x40, 0x78, 0x2f, 0xe5, 0xb3, 0xaf, 0x20, 0x78, 0x0c, 0x56, 0x15, 0x9e, 0xa2, 0x8c, 0x52, 0x9a, 0xb7, 0x50, 0xf7, 0x20, 0x76, 0xd2, 0x50, 0xf2, 0x7f, 0x22, 0x26, 0x68, 0xfe, 0x4e, 0xf7, 0x10, 0xe5, 0x32, 0x77, 0x4f, 0x20, 0xc8, 0x56, 0x25, 0x30, 0x06, 0x0d, 0x1b, 0x48, 0x05, 0xf8, 0x0b, 0x00, 0xd0, 0x87, 0x55, 0x1c, 0xa6, 0x8e, 0xad, 0x35, 0xaa, 0xea, 0x20, 0x53, 0xef, 0x04, 0x0d, 0x7e, 0xcc, 0xdc, 0x34, 0xb7, 0xda, 0x2e, 0xb9, 0x95, 0x5c, 0xc4, 0xe6, 0xd6, 0xd2, 0x04, 0xd5, 0x03, 0x84, 0x17, 0xc7, 0xd7, 0x0c, 0x18, 0xcd, 0x4b, 0xd0, 0x07, 0xfa, 0x04, 0xb5, 0x51, 0xd2, 0x4a, 0x5a, 0x74, 0x7c, 0x09, 0x84, 0x1e, 0x05, 0xc4, 0x50, 0x07, 0x8c, 0x5e, 0x58, 0xd1, 0x83, 0x8b, 0xec, 0x01, 0x88, 0x5c, 0x46, 0x26, 0xe2, 0xd9, 0x4e, 0x29, 0x6d, 0x9d, 0xc7, 0x67, 0x50, 0x4a, 0xbd, 0x00, 0xe1, 0x39, 0x8f, 0xe0, 0x49, 0x8d, 0x2a, 0x0c, 0x56, 0x29, 0x8f, 0xf9, 0xb0, 0x26, 0xc3, 0xd0, 0x36, 0xdc, 0x4e, 0x1c, 0x2c, 0x66, 0xf8, 0xbc, 0x80, 0x19, 0x36, 0xe9, 0x25, 0x97, 0xfe, 0xe7, 0x6b, 0xa6, 0x46, 0x1a, 0xe3, 0x59, 0xfd, 0x91, 0xbc, 0x6f, 0xc8, 0x80, 0x83, 0xd7, 0x00, 0xfc, 0xd5, 0x0d, 0x1e, 0xdb, 0x0d, 0x5a, 0xac, 0x77, 0x62, 0xb7, 0x18, 0x0f, 0x04, 0x42, 0x67, 0x65, 0xd9, 0x05, 0x28, 0x77, 0x2d, 0xa2, 0x54, 0x87, 0x52, 0xd7, 0x23, 0x52, 0x5e, 0x54, 0xbb, 0xf9, 0x3e, 0xdd, 0x03, 0x48, 0x19, 0xaf, 0x65, 0xa8, 0x6a, 0xc0, 0x64, 0xdb, 0x86, 0xfd, 0x05, 0x04, 0x95, 0x0e, 0xb6, 0x02, 0x82, 0x61, 0x77, 0x31, 0xba, 0x01, 0xa6, 0x88, 0x9f, 0xe3, 0x19, 0x4d, 0x54, 0x90, 0x16, 0xc4, 0xb4, 0x09, 0x46, 0x78, 0x29, 0xa5, 0x1e, 0x80, 0xa8, 0x61, 0xb5, 0x2b, 0xa1, 0x7b, 0x31, 0x3f, 0xef, 0x03, 0xcc, 0x6c, 0xd5, 0x80, 0xf1, 0x59, 0x29, 0xac, 0xfe, 0xee, 0xf1, 0xac, 0xfe, 0x82, 0x64, 0xb5, 0x25, 0xef, 0xd6, 0xff, 0xc5, 0xe8, 0xd5, 0x54, 0x40, 0x18, 0x63, 0x6d, 0xa7, 0x13, 0xac, 0x3a, 0xce, 0x1d, 0x21, 0x75, 0xf2, 0x6b, 0x27, 0x39, 0xfd, 0x80, 0xed, 0xf4, 0x03, 0x0b, 0xf4, 0x17, 0xd1, 0x0f, 0x98, 0x21, 0xb3, 0x76, 0xd8, 0x19, 0x94, 0x33, 0x14, 0xd9, 0xf6, 0x30, 0x1a, 0x30, 0x2f, 0x8d, 0x8f, 0x01, 0x00, 0x1d, 0x60, 0x1b, 0x7e, 0xbf, 0x1c, 0x63, 0x53, 0x4a, 0xce, 0xb6, 0x43, 0xe1, 0x96, 0xf1, 0x0e, 0x10, 0xed, 0x43, 0x1c, 0x20, 0x3a, 0x86, 0x3b, 0xa3, 0x0b, 0x06, 0xd4, 0x10, 0x78, 0x0c, 0x5a, 0x51, 0xcb, 0xcf, 0x2d, 0x4a, 0x3c, 0xc7, 0xf2, 0x59, 0xb8, 0xcb, 0x3a, 0xc0, 0xab, 0x06, 0x8c, 0xf2, 0x49, 0x78, 0x0d, 0x7e, 0x5f, 0x40, 0x99, 0xcd, 0x05, 0xac, 0x2c, 0x9e, 0xa7, 0x21, 0xac, 0x49, 0x43, 0x68, 0x83, 0x17, 0xf8, 0xac, 0x8d, 0x13, 0x9e, 0x77, 0x0f, 0x53, 0x55, 0x17, 0x18, 0xcc, 0x1c, 0x27, 0xea, 0xca, 0x85, 0x03, 0xf4, 0x1d, 0xef, 0x9e, 0xa0, 0xf2, 0x02, 0xf6, 0x5e, 0x5d, 0x09, 0x8e, 0xed, 0x08, 0xcd, 0x73, 0xf7, 0x03, 0xef, 0x34, 0x43, 0x66, 0x7e, 0x66, 0x25, 0x4c, 0x40, 0xc1, 0x1f, 0x66, 0xf5, 0x69, 0x71, 0x1b, 0x9e, 0x62, 0xf2, 0xdf, 0x77, 0xea, 0x75, 0x1b, 0x8d, 0x4e, 0x09, 0xf6, 0xb6, 0x1a, 0x46, 0x74, 0x91, 0x22, 0x9d, 0xb7, 0x3b, 0xb6, 0xb8, 0x75, 0x9a, 0xcb, 0x08, 0x07, 0x0c, 0xf1, 0x12, 0x7c, 0x2c, 0xc1, 0x17, 0xc3, 0x84, 0x96, 0x51, 0x5a, 0x3c, 0xed, 0x7a, 0x02, 0xac, 0x55, 0xae, 0x92, 0xe7, 0x65, 0xca, 0x61, 0x0e, 0x75, 0x9c, 0xe6, 0xbe, 0x71, 0xba, 0xeb, 0xd4, 0xfd, 0x47, 0xea, 0x10, 0x31, 0x77, 0xcc, 0x64, 0xf5, 0x83, 0x3f, 0x75, 0x73, 0xff, 0x72, 0x7d, 0x82, 0xac, 0x6e, 0xb4, 0xd8, 0xa1, 0xcf, 0x0b, 0x87, 0x1f, 0x97, 0xf8, 0x1d, 0xbb, 0xac, 0x42, 0xf7, 0x3c, 0x40, 0xb5, 0x95, 0xd4, 0x55, 0xf7, 0x24, 0xe8, 0x12, 0x4b, 0x79, 0x81, 0xd0, 0x69, 0xbf, 0xb7, 0xe2, 0x30, 0x3a, 0x05, 0x04, 0x56, 0x8f, 0x3b, 0xf3, 0x62, 0x4a, 0x1a, 0x9f, 0x71, 0x77, 0x82, 0x7e, 0x40, 0x50, 0x8f, 0xe3, 0x00, 0x1f, 0x77, 0xf6, 0x03, 0x3a, 0x1f, 0x75, 0x81, 0x40, 0x27, 0x3a, 0x10, 0xb2, 0x36, 0x25, 0x70, 0x08, 0x5e, 0x22, 0x20, 0xe4, 0x00, 0x46, 0xd3, 0x20, 0x2d, 0x9c, 0x76, 0x3d, 0x0c, 0xa9, 0x65, 0x54, 0x01, 0x48, 0x39, 0xda, 0x50, 0x0a, 0x0b, 0x8a, 0xd1, 0x04, 0x25, 0x8c, 0x07, 0xa8, 0x12, 0xf9, 0x73, 0xe9, 0x40, 0x47, 0xe3, 0xfc, 0x26, 0x4b, 0x60, 0xdd, 0x82, 0x64, 0x8c, 0xcf, 0x7d, 0xfa, 0x48, 0x4e, 0x89, 0x73, 0xa4, 0xde, 0x03, 0x98, 0xa0, 0xcd, 0x0f, 0xe2, 0x37, 0xa0, 0x3d, 0x80, 0xbf, 0xbf, 0x74, 0x29, 0xcc, 0x02, 0x00, 0xb5, 0xb1, 0xa0, 0x36, 0x45, 0x22, 0xb4, 0x17, 0xb8, 0x48, 0xef, 0x09, 0x6c, 0x08, 0x7a, 0xc3, 0x8c, 0x9e, 0x6d, 0x53, 0x2a, 0x99, 0x2c, 0x06, 0xa5, 0x11, 0x9f, 0xde, 0x48, 0x3b, 0xdb, 0xfc, 0x3c, 0xcd, 0xca, 0x7f, 0x8a, 0x1c, 0x7c, 0xd2, 0x49, 0x0f, 0xb5, 0x2b, 0xd4, 0xf9, 0x84, 0x6b, 0x6b, 0x79, 0x5f, 0x27, 0x8c, 0xe9, 0x7a, 0x90, 0xf4, 0xb8, 0x5d, 0x64, 0x9f, 0xaa, 0xf3, 0x00, 0xd2, 0x42, 0xb9, 0x6b, 0xa4, 0xec, 0x35, 0x20, 0x74, 0x1e, 0x46, 0x2d, 0xa0, 0x56, 0x2f, 0x71, 0x0d, 0x16, 0x95, 0xa0, 0x18, 0xfb, 0x7c, 0x00, 0xc3, 0x94, 0x1d, 0x84, 0xef, 0x9f, 0xc4, 0xca, 0x2f, 0x2a, 0xa0, 0x29, 0x7b, 0xcc, 0x72, 0x84, 0xef, 0x42, 0x6d, 0xd2, 0x54, 0x8a, 0x6e, 0x77, 0x77, 0x83, 0x07, 0x5a, 0xfb, 0xff, 0x61, 0x1a, 0xa0, 0xa4, 0xd0, 0x6a, 0x84, 0xde, 0x61, 0x51, 0x0a, 0x1b, 0xce, 0x17, 0x86, 0x1b, 0xb7, 0x58, 0x61, 0x13, 0x7f, 0x6e, 0x6e, 0x9b, 0x73, 0x54, 0xd2, 0x01, 0x20, 0x87, 0x55, 0xaa, 0xc3, 0x9a, 0x36, 0xbd, 0x0a, 0x00, 0xf4, 0xf3, 0xf5, 0x3f, 0x42, 0x03, 0x68, 0x5a, 0x3c, 0xab, 0x29, 0x87, 0x78, 0xf6, 0xea, 0x95, 0x98, 0x1c, 0x05, 0xc4, 0xf7, 0x08, 0xfe, 0xbb, 0x00, 0x83, 0x91, 0xc1, 0xc3, 0x4b, 0x0b, 0xac, 0x68, 0xc3, 0xd0, 0xb4, 0x60, 0x7b, 0x9b, 0xa9, 0x20, 0x8d, 0xca, 0xf0, 0xe0, 0x2b, 0xea, 0x00, 0xa6, 0x1a, 0x23, 0x54, 0x41, 0xe9, 0x2b, 0xbd, 0x02, 0x91, 0xc4, 0x2e, 0xe7, 0xce, 0x42, 0xf4, 0xa6, 0x10, 0xfc, 0xc2, 0x3c, 0x6b, 0xd3, 0x08, 0x75, 0xef, 0xc0, 0x0d, 0xea, 0x6e, 0x12, 0x71, 0xee, 0x19, 0x98, 0xaa, 0xb6, 0xc0, 0x6c, 0x75, 0x2a, 0x04, 0x63, 0x03, 0xc7, 0xb3, 0x11, 0xfa, 0x3f, 0x00, 0xc8, 0xd5, 0xfb, 0x82, 0xda, 0x0c, 0x41, 0xb3, 0x99, 0x7c, 0xf1, 0xd7, 0xf5, 0x11, 0xf8, 0xc6, 0xf1, 0x3f, 0x31, 0xa3, 0xe6, 0x1c, 0xb1, 0xd3, 0x94, 0x2a, 0xab, 0x73, 0x01, 0xec, 0x6c, 0x03, 0xc1, 0x36, 0xff, 0xd2, 0xe9, 0xd8, 0xca, 0xe9, 0xd8, 0x6a, 0xe8, 0xdf, 0x9b, 0xff, 0x40, 0xa0, 0x8c, 0x5a, 0x5a, 0xd9, 0x6a, 0x3c, 0x7c, 0xfd, 0xf7, 0x31, 0x3b, 0xa4, 0x87, 0x57, 0xed, 0x19, 0x92, 0x1e, 0x2d, 0x6a, 0xff, 0x90, 0x0a, 0xd2, 0x78, 0x3f, 0xc1, 0x03, 0x84, 0x07, 0xa3, 0x53, 0x8b, 0xa7, 0xa8, 0xc2, 0x53, 0x94, 0xd3, 0x24, 0x95, 0x50, 0x4d, 0xf2, 0xe6, 0x89, 0x3a, 0x6d, 0x46, 0xf1, 0x77, 0x5b, 0x9b, 0x87, 0x7c, 0x47, 0x9d, 0x06, 0x11, 0xfc, 0x12, 0x37, 0xef, 0xa7, 0xeb, 0x3b, 0x53, 0xd4, 0xc1, 0x4d, 0xfc, 0x71, 0xee, 0x02, 0xff, 0x43, 0x00, 0xb2, 0xb5, 0x17, 0x18, 0xae, 0x37, 0x19, 0x9d, 0x8d, 0xd1, 0xf3, 0xb4, 0x19, 0x0a, 0x9b, 0xf8, 0x12, 0x00, 0x1c, 0xb5, 0x93, 0x71, 0x7e, 0x69, 0x23, 0x74, 0x6d, 0x96, 0x82, 0x8b, 0x1d, 0x10, 0xbc, 0x04, 0xdb, 0xbc, 0x9b, 0x52, 0x97, 0x85, 0xd7, 0x5f, 0x43, 0xe0, 0xaa, 0x75, 0x7d, 0x07, 0x46, 0x00, 0xc8, 0x81, 0x1f, 0x02, 0x06, 0x3a, 0xd1, 0xc6, 0x68, 0x51, 0xa2, 0x09, 0x2b, 0x1a, 0x97, 0x3b, 0x1b, 0xa9, 0xaa, 0x94, 0xd6, 0x01, 0x44, 0xf5, 0x3d, 0xda, 0x60, 0x49, 0x29, 0xee, 0x2f, 0x67, 0xbe, 0x98, 0xdb, 0x82, 0x2d, 0x73, 0xfd, 0x9c, 0x8d, 0xe4, 0xfc, 0x83, 0xee, 0xca, 0x1f, 0x0b, 0x7e, 0x86, 0x62, 0xa6, 0x56, 0x7d, 0x75, 0x1c, 0x56, 0x70, 0x02, 0xa9, 0xaf, 0xae, 0x23, 0x8e, 0x06, 0xa8, 0x73, 0x41, 0x0d, 0x80, 0xeb, 0x06, 0xcf, 0x21, 0xf7, 0xae, 0xb6, 0xc2, 0x26, 0xff, 0xcc, 0x8c, 0x9a, 0x6d, 0x2b, 0x33, 0x62, 0x27, 0xa3, 0xd4, 0x69, 0x3c, 0x2a, 0x83, 0x92, 0x87, 0xcf, 0x2f, 0x7e, 0x11, 0x77, 0x57, 0xee, 0x1c, 0x71, 0x75, 0xfe, 0xc9, 0x01, 0xa4, 0xec, 0x67, 0x0c, 0xd2, 0xc3, 0x43, 0x2b, 0xdb, 0xf2, 0x23, 0x02, 0x47, 0x34, 0x9b, 0xa8, 0x1e, 0x8d, 0x00, 0xe1, 0xfd, 0x01, 0xc1, 0xaf, 0x70, 0x1b, 0x9d, 0xc7, 0x00, 0xec, 0x61, 0x56, 0x1e, 0x6b, 0x9d, 0x1a, 0x4c, 0xa9, 0x9b, 0xdf, 0x6a, 0x86, 0x4e, 0xff, 0x0d, 0xdf, 0x79, 0xb7, 0x6b, 0x76, 0x2e, 0xd6, 0xad, 0x39, 0x2b, 0xaf, 0xd3, 0x72, 0xbb, 0x6e, 0x79, 0x87, 0x29, 0xa6, 0x5a, 0x27, 0x42, 0xf8, 0xfe, 0x06, 0x80, 0x72, 0x17, 0x80, 0x58, 0xf7, 0x9e, 0x80, 0x28, 0x7d, 0x36, 0x70, 0xa6, 0xda, 0x76, 0x32, 0x43, 0x67, 0xac, 0x36, 0xb7, 0x61, 0x58, 0xf6, 0x0c, 0x16, 0x2b, 0x09, 0xb5, 0x4e, 0xa7, 0xc3, 0xcb, 0x9c, 0x2d, 0xa2, 0xb6, 0xc9, 0xb3, 0x9f, 0xd7, 0x5b, 0xd6, 0xd2, 0xf9, 0xa9, 0x48, 0x3b, 0xf4, 0x6f, 0x62, 0xf5, 0xab, 0xdf, 0xd4, 0x47, 0x66, 0x76, 0xeb, 0x6b, 0x04, 0xff, 0x0a, 0xc1, 0xff, 0xc4, 0x11, 0x4d, 0x2f, 0xda, 0xd1, 0xf0, 0x43, 0xa7, 0x94, 0xd6, 0x3d, 0x45, 0x59, 0x45, 0x20, 0x0b, 0x2e, 0x12, 0x2b, 0x56, 0x51, 0x7e, 0x7e, 0x86, 0xb5, 0x71, 0xcc, 0xb3, 0x04, 0x7f, 0xbb, 0x7b, 0x03, 0xc6, 0x05, 0xaa, 0x2d, 0xb7, 0x94, 0x2b, 0x55, 0x67, 0x80, 0xac, 0xbc, 0xad, 0xf6, 0xfe, 0xd3, 0x99, 0xa3, 0xe7, 0x24, 0xdd, 0x18, 0x21, 0x07, 0x1c, 0x3b, 0x6c, 0xab, 0xf3, 0xb6, 0x63, 0x27, 0xc3, 0x28, 0xef, 0xa1, 0x90, 0x45, 0x6f, 0x9b, 0x91, 0x53, 0xc5, 0x8e, 0xa7, 0x6c, 0x65, 0xa3, 0xe0, 0xfb, 0xc9, 0xd9, 0x22, 0x1c, 0x60, 0xc6, 0xe5, 0xe4, 0x7e, 0x08, 0x81, 0x7f, 0x88, 0x00, 0xa2, 0xdc, 0xa5, 0xd7, 0xc3, 0x08, 0x02, 0x2b, 0x25, 0x35, 0x9a, 0x00, 0xa1, 0x59, 0x6d, 0x69, 0x91, 0x12, 0x4d, 0x80, 0xd1, 0x08, 0x10, 0x0d, 0x2f, 0xb2, 0xea, 0x2b, 0x51, 0x7b, 0x02, 0xdf, 0x8f, 0xea, 0xa7, 0x8d, 0xc3, 0xde, 0xce, 0xe9, 0xc3, 0x68, 0x7d, 0x02, 0xe5, 0x1f, 0x71, 0xcf, 0xfd, 0xae, 0x10, 0x75, 0x5b, 0x8c, 0xda, 0xed, 0x55, 0x77, 0xa1, 0xed, 0x20, 0xe7, 0x63, 0xf5, 0xc9, 0xcf, 0xc9, 0x0d, 0x5e, 0x03, 0xa0, 0x58, 0x90, 0x48, 0x5d, 0x8d, 0xd1, 0x1b, 0x23, 0xaa, 0x2d, 0x9e, 0xcd, 0x44, 0xce, 0xac, 0x58, 0x77, 0xf7, 0xeb, 0xcd, 0x9f, 0x2e, 0x6b, 0x81, 0x82, 0xb8, 0xb2, 0x19, 0x62, 0x65, 0xd2, 0x04, 0xe5, 0x20, 0x84, 0x19, 0x98, 0xa0, 0x8e, 0x38, 0x56, 0x9b, 0x5c, 0x2f, 0x9b, 0x88, 0x7a, 0x1b, 0x4e, 0x57, 0xa8, 0x8e, 0xd0, 0x0a, 0xce, 0x43, 0x03, 0xae, 0xa1, 0xe1, 0xb9, 0x99, 0x41, 0x7e, 0x1f, 0xa0, 0x8d, 0xce, 0xe7, 0x77, 0xd9, 0xbc, 0x8f, 0x72, 0x6a, 0xc5, 0x63, 0x6d, 0x43, 0x17, 0x96, 0x9a, 0x61, 0x13, 0x5e, 0x61, 0xd5, 0xd5, 0xee, 0xce, 0x0d, 0x7c, 0xd7, 0x12, 0x75, 0xfe, 0x2f, 0xce, 0x4d, 0x10, 0x41, 0xfa, 0x96, 0xda, 0x58, 0x63, 0xa4, 0xb5, 0x1b, 0xc1, 0xcb, 0x3d, 0xc9, 0xc1, 0x6b, 0x00, 0x6a, 0x35, 0x00, 0xfa, 0x80, 0xd4, 0x52, 0x5f, 0xae, 0xd2, 0x20, 0x72, 0xc2, 0xc2, 0xbc, 0x2d, 0xaf, 0x46, 0x46, 0x7d, 0xfe, 0x4e, 0x4f, 0xc7, 0xba, 0xbb, 0x2a, 0x98, 0xa8, 0xa9, 0x52, 0x01, 0x15, 0x66, 0x15, 0x7f, 0x0d, 0xf5, 0xc3, 0x10, 0x3a, 0xd4, 0xbb, 0x70, 0x9c, 0xf6, 0xed, 0xb2, 0x2b, 0x98, 0xb2, 0x77, 0x95, 0xd8, 0x99, 0xb0, 0x85, 0x8a, 0xa1, 0x05, 0x33, 0xdd, 0x1d, 0x69, 0x00, 0xc3, 0x30, 0x63, 0x66, 0x2b, 0xca, 0xc7, 0xa3, 0xf2, 0x4f, 0xba, 0x77, 0x7f, 0xa8, 0x23, 0xef, 0x0b, 0x44, 0xd9, 0x6f, 0x25, 0x76, 0x51, 0xfa, 0xbc, 0x4f, 0x1d, 0x77, 0x8d, 0xd0, 0x9b, 0xb5, 0xea, 0x2e, 0x90, 0x86, 0xaf, 0xe0, 0xce, 0x30, 0x0d, 0x80, 0xd2, 0x81, 0x04, 0x7d, 0x27, 0xe8, 0x28, 0x26, 0x35, 0xba, 0x39, 0x69, 0xcd, 0xdb, 0x55, 0x85, 0xf1, 0xb2, 0x29, 0xf4, 0x63, 0x89, 0x8b, 0xfa, 0xc2, 0x57, 0x1b, 0xfe, 0x4a, 0xc5, 0x91, 0x0d, 0xe7, 0x76, 0xc0, 0x10, 0x91, 0x38, 0x1c, 0x5b, 0xda, 0x75, 0x04, 0x3c, 0x07, 0xe7, 0x46, 0x87, 0xb7, 0x97, 0xdf, 0x25, 0xe1, 0xfc, 0x4a, 0x1f, 0xc0, 0x1c, 0x61, 0x89, 0x33, 0x68, 0x6a, 0x52, 0x70, 0x7d, 0x29, 0xc3, 0xdd, 0x31, 0x54, 0xcc, 0xad, 0x73, 0x6d, 0x73, 0x7d, 0x70, 0x28, 0x94, 0x7f, 0xd4, 0xbd, 0x09, 0xea, 0x4a, 0x71, 0xee, 0x04, 0x53, 0x06, 0x67, 0xaa, 0x2e, 0x73, 0x88, 0x9d, 0xba, 0x3f, 0x49, 0x1f, 0x74, 0x14, 0x19, 0x83, 0x02, 0x03, 0xd9, 0xe9, 0x1d, 0x30, 0x08, 0xf5, 0xee, 0xee, 0x90, 0x2a, 0x87, 0x5b, 0x8d, 0x41, 0xde, 0xc4, 0xdf, 0xbc, 0xdd, 0x56, 0x9b, 0x2a, 0x19, 0x09, 0x9b, 0x65, 0xe7, 0xf6, 0xcd, 0x92, 0x94, 0x18, 0x2b, 0x45, 0x29, 0x91, 0x6d, 0x9d, 0xd1, 0xbf, 0xa8, 0x3b, 0xba, 0xe9, 0xec, 0x6e, 0x2b, 0x82, 0x55, 0x8d, 0x56, 0x60, 0x0c, 0x12, 0x89, 0x1e, 0xa4, 0xf7, 0xed, 0xec, 0x5c, 0x9a, 0xa2, 0x02, 0x94, 0x7d, 0xdf, 0x75, 0x88, 0xe6, 0x04, 0xb1, 0xf6, 0x0e, 0x71, 0xda, 0xd9, 0x48, 0x82, 0x57, 0xf9, 0x1e, 0x6e, 0x3c, 0x08, 0x00, 0xb7, 0xa0, 0x2f, 0x97, 0x11, 0xb8, 0xbe, 0x17, 0xf0, 0xcb, 0x94, 0xd7, 0x3a, 0x94, 0xcc, 0x42, 0x9c, 0xac, 0xbb, 0xc0, 0xfe, 0x4f, 0x10, 0x0e, 0xf2, 0xe5, 0x7b, 0x8d, 0xc1, 0x87, 0xa2, 0x67, 0x8e, 0xcb, 0x0d, 0x7b, 0xf1, 0x57, 0xc5, 0xb9, 0xd1, 0xe2, 0x29, 0xda, 0x29, 0x99, 0x89, 0x51, 0x92, 0x91, 0xb2, 0x4b, 0x0a, 0xf2, 0x33, 0xa4, 0xac, 0x74, 0xbf, 0xd5, 0x5c, 0x9a, 0xd9, 0xe9, 0x4f, 0xff, 0xc4, 0x7b, 0x34, 0xea, 0xde, 0x0e, 0x73, 0x8b, 0x71, 0x14, 0xf1, 0xa4, 0x52, 0x28, 0x9d, 0x50, 0x4d, 0x0c, 0x9e, 0x3e, 0x9d, 0xfe, 0x3e, 0x21, 0x48, 0xa7, 0x8b, 0xb9, 0x55, 0x29, 0xfd, 0x9c, 0x10, 0x82, 0xbf, 0x57, 0x9b, 0x1b, 0x75, 0xf4, 0x16, 0x69, 0x2c, 0x06, 0xc0, 0x33, 0x34, 0xe5, 0x95, 0xb5, 0x75, 0xee, 0xf9, 0x71, 0xf2, 0xfd, 0x44, 0xdc, 0xf1, 0x71, 0xbc, 0x57, 0x5a, 0xf8, 0xea, 0x4f, 0x8b, 0x4a, 0x8a, 0x25, 0x26, 0x2a, 0x44, 0xf2, 0x53, 0x23, 0xa4, 0x24, 0x3b, 0x5c, 0xf2, 0xd3, 0xb6, 0x4b, 0xd1, 0xfe, 0x2c, 0xa9, 0xa9, 0x2c, 0x96, 0xa6, 0xc6, 0x3a, 0xe9, 0xe9, 0xe9, 0x90, 0x9e, 0x36, 0x8f, 0xbf, 0x6b, 0x7f, 0x6c, 0x73, 0x6f, 0xec, 0xaa, 0xa6, 0xc3, 0x9b, 0xaf, 0xef, 0x06, 0x8c, 0x23, 0x50, 0xd9, 0x26, 0x8f, 0x61, 0x05, 0x80, 0x6c, 0x33, 0xe4, 0xe8, 0xba, 0x33, 0xd3, 0xec, 0x2d, 0x3a, 0xdf, 0xaf, 0x61, 0xf5, 0x2f, 0x52, 0xfb, 0xf9, 0xea, 0x06, 0x07, 0x2d, 0xb6, 0x6a, 0x4b, 0x5b, 0x31, 0x4e, 0xdd, 0x9e, 0x83, 0x10, 0x07, 0x06, 0xb2, 0xb5, 0x7d, 0x32, 0xae, 0xe4, 0xf8, 0x8f, 0x93, 0x3b, 0x3b, 0xbb, 0x24, 0x37, 0x2b, 0x55, 0xe2, 0x76, 0x6c, 0x92, 0xac, 0x94, 0x18, 0xd9, 0x97, 0xbe, 0x15, 0x30, 0xa2, 0xa4, 0xbc, 0x30, 0x4b, 0xda, 0x5a, 0xea, 0xc5, 0xd7, 0xdb, 0x21, 0x9d, 0x1d, 0x2d, 0xe2, 0x6d, 0xf2, 0x4a, 0x75, 0x4d, 0xb5, 0x55, 0x7e, 0x30, 0xc7, 0x57, 0x91, 0xb2, 0xad, 0xbd, 0x36, 0xe6, 0xbd, 0x96, 0x86, 0x88, 0x55, 0x6d, 0x75, 0x9b, 0x5e, 0xf3, 0x57, 0x6d, 0x7c, 0xb9, 0x2a, 0xb0, 0x79, 0xaa, 0xea, 0xe6, 0x2e, 0xb7, 0x9c, 0x1b, 0xa2, 0xe7, 0xd9, 0x7f, 0x5f, 0xdf, 0x55, 0xda, 0x7d, 0x15, 0x42, 0xf7, 0xcf, 0x5e, 0x6b, 0x9f, 0xf9, 0xe6, 0x88, 0xcc, 0x84, 0x90, 0x9d, 0x25, 0xc5, 0x85, 0x52, 0x5f, 0xef, 0x91, 0xac, 0xb4, 0x04, 0x46, 0xbc, 0x1c, 0x2c, 0xc8, 0x94, 0x8a, 0xe2, 0x3c, 0xa9, 0x28, 0x82, 0x05, 0xe5, 0xf9, 0xd2, 0xe2, 0xad, 0x96, 0xe6, 0x26, 0x8f, 0xd4, 0x7b, 0x6a, 0xa4, 0xa2, 0xa2, 0x4c, 0x0e, 0x16, 0x15, 0x4a, 0x4e, 0x7e, 0x81, 0x24, 0x67, 0x66, 0x4b, 0x5c, 0x62, 0x9a, 0x6c, 0x8b, 0xdb, 0x7d, 0xc8, 0x13, 0xf5, 0xdc, 0x0b, 0xfa, 0xff, 0x05, 0xc2, 0x31, 0x56, 0xce, 0xcd, 0x8e, 0xea, 0x1f, 0x26, 0xc6, 0xd1, 0xd1, 0x8d, 0xd2, 0xf7, 0x23, 0xe6, 0x7c, 0x05, 0x25, 0xee, 0xff, 0x7b, 0x6d, 0x08, 0xfd, 0xfc, 0xfd, 0xd6, 0xd6, 0x16, 0x89, 0xdf, 0x19, 0x21, 0x07, 0x0a, 0x72, 0xa5, 0x84, 0x54, 0xd8, 0x97, 0x9b, 0x21, 0x25, 0x85, 0xb9, 0xe2, 0xa9, 0x2e, 0xd5, 0xab, 0xdf, 0xdb, 0xdd, 0xa6, 0x1f, 0x1b, 0x3c, 0x55, 0x52, 0x53, 0x5d, 0x29, 0xa5, 0x65, 0x25, 0xb2, 0xff, 0xc0, 0x7e, 0xc9, 0xca, 0xc9, 0x91, 0xc4, 0x94, 0x14, 0x49, 0x8e, 0x8b, 0xf0, 0xf4, 0x44, 0xdd, 0xae, 0xea, 0xfb, 0x3c, 0x56, 0x3e, 0x98, 0xe0, 0xa7, 0xeb, 0x43, 0x0c, 0xf5, 0x5f, 0x25, 0x3b, 0x75, 0x43, 0x33, 0x4c, 0xef, 0x46, 0x1f, 0xcf, 0x66, 0xe6, 0xc9, 0xba, 0x3e, 0xff, 0xf8, 0xbd, 0x77, 0xda, 0xdb, 0x5b, 0xa5, 0xa8, 0xb0, 0x40, 0xf6, 0xc4, 0x86, 0x93, 0x06, 0xc9, 0x92, 0x9f, 0x97, 0x23, 0xf9, 0xb9, 0x59, 0x52, 0x4d, 0xfe, 0x77, 0x75, 0x34, 0x69, 0xfa, 0xb7, 0xb7, 0x36, 0x4a, 0x6d, 0x75, 0xb9, 0x14, 0x17, 0xe6, 0x03, 0x50, 0xba, 0x64, 0xc2, 0x94, 0xe4, 0x84, 0x1d, 0xb2, 0x3b, 0x36, 0x42, 0x32, 0xa3, 0x3f, 0x4e, 0x43, 0xe1, 0x27, 0xb8, 0x27, 0xce, 0x13, 0xf5, 0xaa, 0xab, 0x13, 0xe8, 0x38, 0xe7, 0x86, 0x67, 0x3b, 0xe5, 0x5f, 0x70, 0xe5, 0x8f, 0x5d, 0x1f, 0xfe, 0xe9, 0xad, 0xf0, 0x9c, 0xcc, 0x64, 0xa9, 0xab, 0xab, 0x93, 0x82, 0x7d, 0x39, 0x92, 0x9b, 0x91, 0x20, 0xc5, 0x07, 0xb2, 0xa5, 0xac, 0x64, 0x3f, 0xc1, 0x16, 0x00, 0x42, 0x29, 0xd4, 0xaf, 0x47, 0x08, 0xeb, 0xa5, 0xae, 0xb6, 0x4a, 0x4a, 0x4b, 0x0a, 0x65, 0x5f, 0x7e, 0x8e, 0x64, 0x66, 0xa4, 0x4a, 0x72, 0x72, 0xa2, 0xc4, 0xed, 0xd9, 0x2b, 0x05, 0xd1, 0xef, 0xff, 0xce, 0xda, 0xaa, 0xff, 0x79, 0xea, 0x34, 0x45, 0x77, 0xf5, 0x0f, 0x55, 0x9a, 0xf2, 0x6a, 0xeb, 0x2d, 0xe3, 0x04, 0xdd, 0xdc, 0x78, 0xb2, 0xae, 0x3f, 0xbe, 0xf3, 0xe6, 0xcf, 0x95, 0xfa, 0x67, 0xa4, 0xee, 0x91, 0xc2, 0x83, 0xfb, 0x75, 0x70, 0x25, 0x85, 0x79, 0xe2, 0xf5, 0x54, 0x48, 0x67, 0x7b, 0xa3, 0x74, 0x77, 0x22, 0x7c, 0x0d, 0xb5, 0x50, 0xbf, 0x42, 0x2a, 0x2b, 0xcb, 0x75, 0x8a, 0x14, 0xec, 0x2f, 0x90, 0xcc, 0xac, 0x6c, 0x89, 0x4f, 0x4c, 0x91, 0xdc, 0xd8, 0x4f, 0x3e, 0x50, 0x9f, 0xa3, 0x0f, 0x2c, 0x94, 0xc8, 0xa9, 0x83, 0x4b, 0x5c, 0xa6, 0x9d, 0xe3, 0x50, 0xfe, 0x84, 0xde, 0xdf, 0x7b, 0x32, 0xae, 0xab, 0x96, 0x5e, 0x3e, 0x3c, 0x6c, 0xdd, 0xfb, 0x21, 0x29, 0x7b, 0xb6, 0x4b, 0x5e, 0x56, 0xa2, 0x1c, 0xd8, 0x97, 0xad, 0xe9, 0xaf, 0x56, 0xbf, 0xad, 0xa5, 0x41, 0x7a, 0x7b, 0xda, 0xa5, 0xb5, 0xb9, 0x41, 0x2a, 0x2b, 0x4a, 0x65, 0x7f, 0x41, 0xbe, 0x64, 0x65, 0x65, 0x48, 0x52, 0x52, 0xa2, 0xec, 0xde, 0x15, 0x2b, 0xdb, 0xa2, 0x63, 0xa5, 0x62, 0xcf, 0x9a, 0x15, 0xea, 0x73, 0xb4, 0xb3, 0x54, 0xfb, 0x0c, 0x6a, 0xcf, 0x51, 0xfd, 0xc3, 0x55, 0xe3, 0xbf, 0x78, 0xe0, 0x5f, 0xbe, 0x16, 0xcc, 0x9d, 0x33, 0xfa, 0xb9, 0x67, 0x9f, 0x6a, 0x88, 0x8b, 0x0e, 0x97, 0x8a, 0x92, 0x7d, 0xd2, 0x50, 0x57, 0x2e, 0xf5, 0x75, 0x95, 0x50, 0xde, 0x19, 0x9e, 0xba, 0x6a, 0xa9, 0xae, 0xaa, 0x90, 0xe2, 0xa2, 0x83, 0x92, 0x97, 0x97, 0x2b, 0xe9, 0xe9, 0xe9, 0x92, 0x98, 0x9c, 0x2c, 0xdb, 0x63, 0xe2, 0x0f, 0xe6, 0xc7, 0xad, 0xba, 0x41, 0x7d, 0xc6, 0x91, 0xaf, 0xd2, 0xc6, 0x9e, 0xa4, 0x6b, 0x37, 0x43, 0xde, 0xfc, 0xe5, 0xab, 0x92, 0x9f, 0x93, 0x2e, 0xbd, 0x5d, 0xad, 0x72, 0xa8, 0xbf, 0x47, 0xda, 0x10, 0x3f, 0x95, 0xfb, 0xe5, 0xe5, 0x25, 0x72, 0x00, 0xe5, 0xcf, 0xc9, 0xcd, 0x95, 0x94, 0xd4, 0x54, 0x89, 0xdf, 0x93, 0x20, 0xab, 0x57, 0xaf, 0xbe, 0xf1, 0x54, 0x4f, 0xfa, 0x84, 0x5d, 0x77, 0xdd, 0x75, 0xd7, 0xf2, 0x15, 0x2b, 0x56, 0x88, 0x02, 0x41, 0x8d, 0x37, 0x5e, 0x7f, 0x4d, 0x52, 0x92, 0xf6, 0x48, 0x55, 0x65, 0x19, 0xb5, 0xbf, 0x56, 0xe7, 0x7f, 0x6e, 0x6e, 0x8e, 0xec, 0xdd, 0xbb, 0x97, 0xe0, 0xf7, 0xc8, 0x07, 0x1f, 0x7e, 0xb4, 0xea, 0x54, 0xcf, 0xf9, 0x84, 0x5f, 0xef, 0xbe, 0xfb, 0xee, 0x9a, 0xcf, 0x3e, 0xfb, 0x4c, 0x5e, 0x7e, 0xf9, 0x65, 0x59, 0xb8, 0x68, 0xb1, 0x06, 0x62, 0xc9, 0x92, 0x4b, 0xe4, 0xd5, 0x57, 0x7f, 0x2e, 0x1b, 0x36, 0x84, 0x4a, 0x6a, 0x5a, 0x6a, 0x75, 0x5a, 0x7a, 0x7a, 0xd9, 0x96, 0xf0, 0x88, 0xf7, 0x6e, 0xbc, 0xe9, 0xe6, 0x7f, 0xad, 0xff, 0xf7, 0x3b, 0x51, 0xd7, 0xf2, 0xe5, 0xcb, 0x97, 0xae, 0x5d, 0xbb, 0x36, 0x66, 0xfd, 0xfa, 0xf5, 0xbd, 0x6b, 0xd6, 0xac, 0xb1, 0xef, 0xb8, 0xe3, 0x0e, 0x93, 0x5f, 0x17, 0xa9, 0x97, 0x96, 0x2e, 0x5d, 0x3a, 0xf2, 0xb6, 0x65, 0xcb, 0x86, 0x9d, 0xea, 0x39, 0x7e, 0x25, 0xd7, 0xca, 0x95, 0x2b, 0x6f, 0xf9, 0xe8, 0xa3, 0x8f, 0x3e, 0x7d, 0xe3, 0x8d, 0x37, 0x56, 0x05, 0x05, 0x05, 0x4d, 0x3c, 0xd5, 0xf3, 0xf9, 0xf7, 0xf5, 0xef, 0xeb, 0x9f, 0xbb, 0xfe, 0x1b, 0x51, 0xc4, 0x30, 0xee, 0x50, 0x54, 0x7e, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/messagebox.cpp000077500000000000000000000254141516402577000244750ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined __WIN32__ # include #elif defined __HAIKU__ # include #endif S::Int S::GUI::Dialogs::MessageDlg::nOfMessageBoxes = 0; S::Bool S::GUI::Dialogs::MessageDlg::defaultRightToLeft = False; S::Int S::GUI::Dialogs::QuickMessage(const String &text, const String &title, Int buttons, const Bitmap &icon) { MessageDlg *app = new MessageDlg(text, title, buttons, icon); app->ShowDialog(); Int rVal = app->GetButtonCode(); Object::DeleteObject(app); return rVal; } S::Int S::GUI::Dialogs::QuickMessage(const String &text, const String &title, Int buttons, Int iconID) { MessageDlg *app = new MessageDlg(text, title, buttons, iconID); app->ShowDialog(); Int rVal = app->GetButtonCode(); Object::DeleteObject(app); return rVal; } S::GUI::Dialogs::MessageDlg::MessageDlg(const String &text, const String &title, Int buttons, const Bitmap &icon, const String &checkBoxText, Bool *cVar) { InitializeWidgets(text, title, buttons, icon, checkBoxText, cVar); } S::GUI::Dialogs::MessageDlg::MessageDlg(const String &text, const String &title, Int buttons, Int iconID, const String &checkBoxText, Bool *cVar) { /* Load message box icon if any. */ Bitmap icon; #ifdef __WIN32__ icon = ImageLoader::Load(String("Icon:").Append(String::FromInt(iconID))); #else String iconName; Int iconSize = 32; if (iconID == Message::Icon::Error) iconName = "dialog-error.png"; else if (iconID == Message::Icon::Question) iconName = "dialog-question.png"; else if (iconID == Message::Icon::Warning) iconName = "dialog-warning.png"; else if (iconID == Message::Icon::Information) iconName = "dialog-information.png"; static const char *iconDirs[] = { "%RESOURCESDIR%/icons", "/usr/share/icons", "/usr/local/share/icons", NIL }; for (Int i = 0; iconDirs[i] != NIL; i++) { String iconDir = String(iconDirs[i]).Replace("%RESOURCESDIR%", S::System::System::GetResourcesDirectory()); if (!Directory(iconDir).Exists()) continue; String file = String(iconDir).Append("/gnome/").Append(String::FromInt(iconSize)).Append("x").Append(String::FromInt(iconSize)).Append("/status/").Append(iconName); if (!File(file).Exists()) continue; icon = ImageLoader::Load(file); break; } #endif /* Mirror question mark icon for Arabic script languages. */ if (iconID == Message::Icon::Question && I18n::Translator::defaultTranslator->TranslateString("?")[0] == 0x61F) { Point point; Size size = icon.GetSize(); for (point.y = 0; point.y < size.cy; point.y++) { for (point.x = 0; point.x < size.cx / 2; point.x++) { Point mirror = Point(size.cx - point.x - 1, point.y); Color pointPixel = icon.GetPixel(point); Color mirrorPixel = icon.GetPixel(mirror); icon.SetPixel(point, mirrorPixel); icon.SetPixel(mirror, pointPixel); } } } /* Create message box widgets. */ InitializeWidgets(text, title, buttons, icon, checkBoxText, cVar); } S::Bool S::GUI::Dialogs::MessageDlg::InitializeWidgets(const String &iText, const String &title, Int iButtons, const Bitmap &bitmap, const String &checkBoxText, Bool *iCVar) { text = iText; cVar = iCVar; buttons = iButtons; buttonCode = -1; msgbox = new Window(title, Point(), Size()); msgbox->SetRightToLeft(defaultRightToLeft); msgbox->SetFlags(msgbox->GetFlags() | WF_MODAL); titlebar = new Titlebar(TB_CLOSEBUTTON); layer = new Layer(); icon = new Image(bitmap, Point(14, 19), Size(32, 32)); /* Compute message box size. */ Int maxSize = 0; Int buttonWidth = 80; Int buttonHeight = 22; GUI::Font font; const Array &lines = text.Explode("\n"); foreach (const String &line, lines) { Int textSize = font.GetUnscaledTextSizeX(line); if (textSize > maxSize) maxSize = textSize; } msgbox->SetWidth(maxSize + 36); msgbox->SetHeight((((Int) Math::Max(2, lines.Length()) + 1) * 16) + 70 + buttonHeight); if (bitmap != NIL) msgbox->SetWidth(maxSize + 36 + icon->GetWidth() + 20); Int titleSize = Font(Font::Default, Font::DefaultSize, Font::Bold).GetUnscaledTextSizeX(title); msgbox->SetWidth(Math::Max(msgbox->GetWidth(), titleSize + 80)); /* Add widgets. */ Add(msgbox); msgbox->Add(titlebar); msgbox->Add(layer); msgbox->Add(icon); msgbox->onPaint.Connect(&MessageDlg::MessagePaintProc, this); msgbox->doClose.Connect(&MessageDlg::MessageKillProc, this); /* Add optional checkbox. */ checkbox = NIL; if (cVar != NIL) { checkbox = new CheckBox(checkBoxText, Point(13, 46 + buttonHeight), Size(100, 0), cVar); checkbox->SetOrientation(OR_LOWERLEFT); checkbox->SetWidth(checkbox->GetUnscaledTextWidth() + 21); msgbox->SetWidth(Math::Max(msgbox->GetWidth(), checkbox->GetUnscaledTextWidth() + 54)); msgbox->SetHeight(msgbox->GetHeight() + 22); if (bitmap != NIL) { checkbox->SetX(checkbox->GetX() + icon->GetWidth() + 20); msgbox->SetWidth(Math::Max(msgbox->GetWidth(), checkbox->GetUnscaledTextWidth() + 54 + icon->GetWidth() + 20)); } layer->Add(checkbox); } /* Find button labels. */ switch (buttons) { default: case Message::Buttons::Ok: buttonLabels.Add("OK"); break; case Message::Buttons::OkCancel: buttonLabels.Add("OK"); buttonLabels.Add("Cancel"); break; case Message::Buttons::YesNo: buttonLabels.Add("Yes"); buttonLabels.Add("No"); break; case Message::Buttons::YesNoCancel: buttonLabels.Add("Yes"); buttonLabels.Add("No"); buttonLabels.Add("Cancel"); break; case Message::Buttons::RetryCancel: buttonLabels.Add("Retry"); buttonLabels.Add("Cancel"); break; case Message::Buttons::AbortRetryIgnore: buttonLabels.Add("Abort"); buttonLabels.Add("Retry"); buttonLabels.Add("Ignore"); break; } /* Add buttons. */ msgbox->SetWidth(Math::Max(msgbox->GetWidth(), buttonLabels.Length() * (buttonWidth + 9) + 21)); foreach (const String &buttonLabel, buttonLabels) { Button *button = new Button(I18n::Translator::defaultTranslator->TranslateString(buttonLabel), Point((msgbox->GetWidth() - (buttonLabels.Length() * (buttonWidth + 9) - 9)) / 2 - 3 + (foreachindex * (buttonWidth + 9)), 14 + buttonHeight), Size()); if (foreachindex == 0) button->onAction.Connect(&MessageDlg::MessageButton0, this); else if (foreachindex == 1) button->onAction.Connect(&MessageDlg::MessageButton1, this); else if (foreachindex == 2) button->onAction.Connect(&MessageDlg::MessageButton2, this); button->SetOrientation(OR_LOWERLEFT); buttonWidgets.Add(button); layer->Add(button); } /* Position message box on screen. */ Rect workArea = System::Screen::GetActiveScreenWorkArea(); Float scaleFactor = Surface().GetSurfaceDPI() / 96.0; msgbox->SetPosition(workArea.GetPosition() + Point((workArea.GetWidth() - Math::Round(msgbox->GetWidth() * scaleFactor)) / 2, (workArea.GetHeight() - Math::Round(msgbox->GetHeight() * scaleFactor)) / 2) + Point(nOfMessageBoxes * 25, nOfMessageBoxes * 25)); return True; } S::GUI::Dialogs::MessageDlg::~MessageDlg() { foreach (Button *button, buttonWidgets) DeleteObject(button); DeleteObject(layer); DeleteObject(icon); DeleteObject(titlebar); DeleteObject(msgbox); if (checkbox != NIL) DeleteObject(checkbox); } const Error &S::GUI::Dialogs::MessageDlg::ShowDialog() { nOfMessageBoxes++; #if defined __WIN32__ MessageBeep(MB_ICONASTERISK); #elif defined __HAIKU__ beep(); #endif msgbox->WaitUntilClosed(); return error; } S::Void S::GUI::Dialogs::MessageDlg::MessagePaintProc() { const Array &lines = text.Explode("\n"); /* Get text bounds. */ Layer *mainLayer = msgbox->GetMainLayer(); Surface *surface = msgbox->GetDrawSurface(); Rect textRect = Rect(mainLayer->GetRealPosition() + Point(14, 19) * surface->GetSurfaceDPI() / 96.0, mainLayer->GetRealSize() - Size(28, 19) * surface->GetSurfaceDPI() / 96.0); if (icon->GetBitmap() != NIL) { if (lines.Length() == 1) textRect.top += Math::Round(8 * surface->GetSurfaceDPI() / 96.0); textRect.left += icon->GetRealSize().cx + Math::Round(20 * surface->GetSurfaceDPI() / 96.0); } /* Draw message text. */ Font font; font.SetColor(Setup::TextColor); foreach (const String &line, lines) { surface->SetText(line, textRect, font); textRect.top += Math::Round(16 * surface->GetSurfaceDPI() / 96.0); } } S::Bool S::GUI::Dialogs::MessageDlg::MessageKillProc() { if (buttonCode == 0) buttonCode = Message::Button::Close; nOfMessageBoxes--; return True; } S::Void S::GUI::Dialogs::MessageDlg::MessageButton(Int buttonID) { if (buttonLabels.GetNth(buttonID) == "OK") buttonCode = Message::Button::Ok; else if (buttonLabels.GetNth(buttonID) == "Cancel") buttonCode = Message::Button::Cancel; else if (buttonLabels.GetNth(buttonID) == "Yes") buttonCode = Message::Button::Yes; else if (buttonLabels.GetNth(buttonID) == "No") buttonCode = Message::Button::No; else if (buttonLabels.GetNth(buttonID) == "Retry") buttonCode = Message::Button::Retry; else if (buttonLabels.GetNth(buttonID) == "Abort") buttonCode = Message::Button::Abort; else if (buttonLabels.GetNth(buttonID) == "Ignore") buttonCode = Message::Button::Ignore; msgbox->Close(); } S::Void S::GUI::Dialogs::MessageDlg::MessageButton0() { MessageButton(0); } S::Void S::GUI::Dialogs::MessageDlg::MessageButton1() { MessageButton(1); } S::Void S::GUI::Dialogs::MessageDlg::MessageButton2() { MessageButton(2); } S::Int S::GUI::Dialogs::MessageDlg::GetButtonCode() const { return buttonCode; } S::Void S::GUI::Dialogs::MessageDlg::SetRightToLeft(Bool rightToLeft) { msgbox->SetRightToLeft(rightToLeft); } S::Bool S::GUI::Dialogs::MessageDlg::IsRightToLeft() const { return msgbox->IsRightToLeft(); } S::Void S::GUI::Dialogs::MessageDlg::SetDefaultRightToLeft(Bool nDefaultRightToLeft) { defaultRightToLeft = nDefaultRightToLeft; } S::Bool S::GUI::Dialogs::MessageDlg::IsDefaultRightToLeft() { return defaultRightToLeft; } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/splashscreen.cpp000077500000000000000000000044701516402577000250310ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include S::GUI::Dialogs::SplashScreen::SplashScreen(const GUI::Bitmap &iBitmap, Int iTime) { timer = new System::Timer(); time = iTime; bitmap = iBitmap; Rect workArea = System::Screen::GetActiveScreenWorkArea(); Float scaleFactor = Surface().GetSurfaceDPI() / 96.0; Size size = bitmap.GetSize(); splashscreen = new Window("Splash screen", Point(), size + Size(2, 2)); splashscreen->SetPosition(workArea.GetPosition() + Point((workArea.GetWidth() - Math::Round((size.cx + 2) * scaleFactor)) / 2, (workArea.GetHeight() - Math::Round((size.cy + 2) * scaleFactor)) / 2)); splashscreen->onPaint.Connect(&SplashScreen::SplashPaintProc, this); splashscreen->doClose.Connect(&SplashScreen::SplashKillProc, this); splashscreen->SetFlags(WF_NORESIZE | WF_TOPMOST); Add(splashscreen); timer->onInterval.Connect(&SplashScreen::TimerProc, this); } S::GUI::Dialogs::SplashScreen::~SplashScreen() { DeleteObject(splashscreen); DeleteObject(timer); } const Error &S::GUI::Dialogs::SplashScreen::ShowDialog() { splashscreen->Show(); timer->Start(time); splashscreen->WaitUntilClosed(); return error; } S::Void S::GUI::Dialogs::SplashScreen::SplashPaintProc() { Surface *surface = splashscreen->GetDrawSurface(); Rect bmpRect; bmpRect.left = 1; bmpRect.top = 1; bmpRect.right = bmpRect.left + bitmap.GetSize().cx; bmpRect.bottom = bmpRect.top + bitmap.GetSize().cy; surface->BlitFromBitmap(bitmap, Rect(Point(0, 0), bitmap.GetSize()), bmpRect); } S::Bool S::GUI::Dialogs::SplashScreen::SplashKillProc() { timer->Stop(); return True; } S::Void S::GUI::Dialogs::SplashScreen::TimerProc() { splashscreen->Close(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/dialogs/tipodaydlg.cpp000077500000000000000000000140361516402577000244760ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include S::GUI::Dialogs::TipOfTheDay::TipOfTheDay(Bool *iShowTips) { showTips = iShowTips; mode = TIP_ORDERED; offset = 0; dlgwnd = new Window(I18n::Translator::defaultTranslator->TranslateString("Tip of the day"), Point(200, 200), Size(350, 300)); titlebar = new Titlebar(TB_CLOSEBUTTON); divbar = new Divider(39, OR_HORZ | OR_BOTTOM); btn_ok = new Button(I18n::Translator::defaultTranslator->TranslateString("OK"), Point(87, 29), Size()); btn_ok->onAction.Connect(&TipOfTheDay::OnOK, this); btn_ok->SetOrientation(OR_LOWERRIGHT); btn_next = new Button(I18n::Translator::defaultTranslator->TranslateString("Next tip"), Point(175, 29), Size()); btn_next->onAction.Connect(&TipOfTheDay::OnNext, this); btn_next->SetOrientation(OR_LOWERRIGHT); btn_next->SetWidth(Math::Max(80, btn_next->GetUnscaledTextWidth() + 13)); btn_next->SetX(btn_next->GetWidth() + 95); check_showtips = new CheckBox(I18n::Translator::defaultTranslator->TranslateString("Show tips on startup"), Point(7, 27), Size(150, 0), showTips); check_showtips->SetOrientation(OR_LOWERLEFT); check_showtips->SetWidth(check_showtips->GetUnscaledTextWidth() + 21); Buffer light(sizeof(Icons::Light)); memcpy(light, Icons::Light, sizeof(Icons::Light)); img_light = new Image(ImageLoader::Load(light, IMAGE_FORMAT_PNG), Point(8, 3), Size(32, 32)); txt_didyouknow = new Text(I18n::Translator::defaultTranslator->TranslateString("Did you know..."), Point(11 + img_light->GetWidth(), 7)); txt_didyouknow->SetFont(Font(Font::Default, 14, Font::Bold, 0, txt_didyouknow->GetFont().GetColor())); txt_tip = new Cursor(Point(6, 4), Size(328, 182)); txt_tip->SetFont(Font(Font::Default, Font::DefaultSize, Font::Normal, 0, Setup::TooltipTextColor)); txt_tip->SetFlags(CF_MULTILINE); txt_tip->Deactivate(); layer_inner = new Layer(); layer_inner->SetMetrics(Point(8, 39), Size(328, 182)); layer_inner->SetBackgroundColor(Setup::TooltipColor); Add(dlgwnd); dlgwnd->Add(titlebar); dlgwnd->Add(divbar); dlgwnd->Add(btn_ok); dlgwnd->Add(btn_next); dlgwnd->Add(check_showtips); dlgwnd->Add(img_light); dlgwnd->Add(txt_didyouknow); dlgwnd->GetMainLayer()->Add(layer_inner); layer_inner->Add(txt_tip); dlgwnd->SetFlags(dlgwnd->GetFlags() | WF_MODAL); dlgwnd->onPaint.Connect(&TipOfTheDay::OnPaint, this); } S::GUI::Dialogs::TipOfTheDay::~TipOfTheDay() { DeleteObject(dlgwnd); DeleteObject(titlebar); DeleteObject(divbar); DeleteObject(btn_ok); DeleteObject(btn_next); DeleteObject(check_showtips); DeleteObject(img_light); DeleteObject(txt_didyouknow); DeleteObject(layer_inner); DeleteObject(txt_tip); } const Error &S::GUI::Dialogs::TipOfTheDay::ShowDialog() { if (caption != NIL) dlgwnd->SetText(caption); /* Compute and set dialog size. */ Rect workArea = System::Screen::GetActiveScreenWorkArea(); Float scaleFactor = Surface().GetSurfaceDPI() / 96.0; Int additionalSize = Math::Max(0, check_showtips->GetWidth() + btn_next->GetWidth() - 234); Size size = Size(328 + additionalSize, 182); foreach (const String &tip, tips) size = Size(Math::Max(size.cx, font.GetUnscaledTextSizeX(tip) + 12), Math::Max(size.cy, font.GetUnscaledTextSizeY(tip) + 12)); dlgwnd->SetSize(Size(24, 120) + size); dlgwnd->SetPosition(workArea.GetPosition() + Point((workArea.GetWidth() - Math::Round(dlgwnd->GetWidth() * scaleFactor)) / 2, (workArea.GetHeight() - Math::Round(dlgwnd->GetHeight() * scaleFactor)) / 2)); layer_inner->SetSize(size); txt_tip->SetSize(size); /* Set next tip and display dialog. */ if (offset >= tips.Length()) offset = 0; OnNext(); if (tips.Length() <= 1) btn_next->Deactivate(); dlgwnd->Show(); dlgwnd->WaitUntilClosed(); return error; } S::Int S::GUI::Dialogs::TipOfTheDay::AddTip(const String &tip) { tips.Add(tip); return Success(); } S::Int S::GUI::Dialogs::TipOfTheDay::SetMode(Int nMode, Int nOffset, Bool showOnStartup) { switch (nMode) { case TIP_ORDERED: mode = nMode; offset = nOffset; break; case TIP_RANDOM: mode = nMode; offset = 0; break; default: return Error(); } *showTips = showOnStartup; return Success(); } S::Int S::GUI::Dialogs::TipOfTheDay::GetOffset() const { return offset; } S::Void S::GUI::Dialogs::TipOfTheDay::OnOK() { dlgwnd->Close(); } S::Void S::GUI::Dialogs::TipOfTheDay::OnNext() { if (tips.Length() <= 1) return; String tip; switch (mode) { case TIP_ORDERED: tip = tips.GetNth(offset++); if (offset == tips.Length()) offset = 0; break; case TIP_RANDOM: Math::RandomSeed(); do { tip = tips.GetNth(Math::Random() % tips.Length()); } while (tip == txt_tip->GetText()); break; } txt_tip->SetText(tip); OnPaint(); } S::Void S::GUI::Dialogs::TipOfTheDay::OnPaint() { dlgwnd->GetDrawSurface()->Box(Rect(layer_inner->GetRealPosition() - Point(1, 1), layer_inner->GetRealSize() + Size(2, 2)), 0, Rect::Outlined); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/000077500000000000000000000000001516402577000216475ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/Makefile000066400000000000000000000011751516402577000233130ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = layer.o widget.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,basic) ALLCMD2 = $(call makein,hotspot) ALLCMD3 = $(call makein,multi) ALLCMD4 = $(call makein,special) CLEANCMD1 = $(call cleanin,basic) CLEANCMD2 = $(call cleanin,hotspot) CLEANCMD3 = $(call cleanin,multi) CLEANCMD4 = $(call cleanin,special) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/000077500000000000000000000000001516402577000227305ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/Makefile000066400000000000000000000007531516402577000243750ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. # Enter object files here: OBJECTS = activearea.o arrows.o button.o checkbox.o client.o divider.o editbox.o groupbox.o hyperlink.o image.o multiedit.o optionbox.o progressbar.o scrollbar.o slider.o statusbar.o tabwidget.o text.o titlebar.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/activearea.cpp000077500000000000000000000033751516402577000255530ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::GUI::ActiveArea::classID = S::Object::RequestClassID(); S::GUI::ActiveArea::ActiveArea(const Color &iColor, const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { type = classID; areaColor = iColor; if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(20); hotspot = new Hotspot(Point(1, 1), GetSize() - Size(2, 2)); hotspot->onLeftButtonClick.Connect(&onAction); Add(hotspot); onChangeSize.Connect(&ActiveArea::OnChangeSize, this); } S::GUI::ActiveArea::~ActiveArea() { DeleteObject(hotspot); } S::Int S::GUI::ActiveArea::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->Box(frame + Point(1, 1) - Size(2, 2), areaColor, Rect::Filled); surface->Frame(frame, FRAME_DOWN); } break; } return Success(); } S::Int S::GUI::ActiveArea::SetColor(const Color &nColor) { areaColor = nColor; Paint(SP_PAINT); return Success(); } S::Void S::GUI::ActiveArea::OnChangeSize(const Size &nSize) { hotspot->SetSize(nSize - Size(2, 2)); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/arrows.cpp000077500000000000000000000154041516402577000247600ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include const S::Short S::GUI::Arrows::classID = S::Object::RequestClassID(); S::GUI::Arrows::Arrows(const Point &iPos, const Size &iSize, Int sType, Int *var, Int rangeStart, Int rangeEnd) : Widget(iPos, iSize) { type = classID; subtype = sType; startValue = rangeStart; endValue = rangeEnd; stepSize = 1; dummyVariable = 0; if (var == NIL) variable = &dummyVariable; else variable = var; SetValue(*variable); timer = NIL; timerCount = 0; timerDirection = 1; if (GetWidth() == 0) SetWidth(subtype == OR_VERT ? 17 : 24); if (GetHeight() == 0) SetHeight(subtype == OR_VERT ? 24 : 17); onRangeChange.SetParentObject(this); onValueChange.SetParentObject(this); onValueChange.Connect(&onAction); SetBackgroundColor(Setup::BackgroundColor); arrow1Hotspot = new HotspotSimpleButton(Point(2 + (subtype == OR_HORZ ? GetWidth() / 2 : 0), 2), GetSize() - Size(4 + (subtype == OR_HORZ ? GetWidth() / 2 : 0), 4 + (subtype == OR_HORZ ? 0 : GetHeight() / 2))); arrow2Hotspot = new HotspotSimpleButton(Point(2, 2 + (subtype == OR_VERT ? GetHeight() / 2 : 0)), GetSize() - Size(4 + (subtype == OR_HORZ ? GetWidth() / 2 : 0), 4 + (subtype == OR_HORZ ? 0 : GetHeight() / 2))); arrow1Hotspot->onLeftButtonDown.Connect(&Arrows::OnMouseDownPlus, this); arrow2Hotspot->onLeftButtonDown.Connect(&Arrows::OnMouseDownMinus, this); arrow1Hotspot->onLeftButtonUp.Connect(&Arrows::OnMouseRelease, this); arrow2Hotspot->onLeftButtonUp.Connect(&Arrows::OnMouseRelease, this); Add(arrow1Hotspot); Add(arrow2Hotspot); onChangeSize.Connect(&Arrows::OnChangeSize, this); } S::GUI::Arrows::~Arrows() { if (timer != NIL) { timer->Stop(); DeleteObject(timer); timer = NIL; } DeleteObject(arrow1Hotspot); DeleteObject(arrow2Hotspot); } S::Int S::GUI::Arrows::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Int arrowColor = Setup::TextColor; if (!IsActive()) arrowColor = Setup::InactiveTextColor; switch (message) { case SP_PAINT: surface->StartPaint(frame); surface->Frame(frame, FRAME_UP); if (subtype == OR_HORZ) { Point lineStart = Point((frame.left + frame.right) / 2 - 1, frame.top + 1); Point lineEnd = Point(lineStart.x, frame.bottom - 1); surface->Line(lineStart, lineEnd, Setup::DividerDarkColor); surface->Line(lineStart + Point(1, 0), lineEnd + Point(1, 0), Setup::DividerLightColor); Int size = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); Point offset = Point((size % 2) ? 1 : 0, (frame.GetHeight() % 2) ? 0 : 1); for (Int i = 0; i < size; i++) { lineStart = Point((frame.left + frame.GetWidth() / 4) - size / 2 + i - offset.x, frame.top + frame.GetHeight() / 2 - i - offset.y); lineEnd = lineStart + Point(0, 2 * i + 1); surface->Line(lineStart, lineEnd, arrowColor); } for (Int j = 0; j < size; j++) { lineStart = Point((frame.right - frame.GetWidth() / 4) - (size + 1) / 2 + j, frame.top + frame.GetHeight() / 2 - size + 1 + j - offset.y); lineEnd = lineStart + Point(0, 2 * (size - j) - 1); surface->Line(lineStart, lineEnd, arrowColor); } } else if (subtype == OR_VERT) { Point lineStart = Point(frame.left + 1, (frame.top + frame.bottom) / 2 - 1); Point lineEnd = Point(frame.right - 1, lineStart.y); surface->Line(lineStart, lineEnd, Setup::DividerDarkColor); surface->Line(lineStart + Point(0, 1), lineEnd + Point(0, 1), Setup::DividerLightColor); Int size = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); for (Int i = 0; i < size; i++) { lineStart = Point(frame.left + frame.GetWidth() / 2 + (IsRightToLeft() ? 1 : 0) - i, (frame.top + frame.GetHeight() / 4) - size / 2 + i); lineEnd = lineStart + Point(2 * i + 1, 0); surface->Line(lineStart, lineEnd, arrowColor); } for (Int j = 0; j < size; j++) { lineStart = Point(frame.left + frame.GetWidth() / 2 + (IsRightToLeft() ? 1 : 0) - size + 1 + j, (frame.bottom - frame.GetHeight() / 4) - (size + 1) / 2 + j); lineEnd = lineStart + Point(2 * (size - j) - 1, 0); surface->Line(lineStart, lineEnd, arrowColor); } } surface->EndPaint(); break; } return Success(); } S::Void S::GUI::Arrows::OnMouseDownPlus() { if (timer == NIL) { timer = new System::Timer(); timer->onInterval.Connect(&Arrows::OnTimer, this); timer->Start(0); timerCount = 0; timerDirection = 1; } } S::Void S::GUI::Arrows::OnMouseDownMinus() { if (timer == NIL) { timer = new System::Timer(); timer->onInterval.Connect(&Arrows::OnTimer, this); timer->Start(0); timerCount = 0; timerDirection = -1; } } S::Void S::GUI::Arrows::OnMouseRelease() { if (timer != NIL) { timer->Stop(); DeleteObject(timer); timer = NIL; } } S::Void S::GUI::Arrows::OnTimer() { if (timerCount == 0) { timer->Stop(); timer->Start(250); } if (timerCount == 1) { timer->Stop(); timer->Start(100); } Int prevValue = *variable; Int difference = timerDirection; for (Int n = 1; n <= 8; n++) { if (timerCount >= 8 * n) difference = timerDirection * (Int) Math::Pow(2, n); } *variable = Math::Min(Math::Max(*variable + difference * Int(stepSize), startValue), endValue); if (*variable != prevValue) onValueChange.Emit(*variable); timerCount++; } S::Int S::GUI::Arrows::SetRange(Int rangeStart, Int rangeEnd) { if (startValue == rangeStart && endValue == rangeEnd) return Success(); startValue = rangeStart; endValue = rangeEnd; SetValue(*variable); onRangeChange.Emit(startValue, endValue); return Success(); } S::Void S::GUI::Arrows::SetValue(Int newValue) { Int prevValue = *variable; *variable = Math::Min(Math::Max(newValue, startValue), endValue); if (*variable != prevValue) onValueChange.Emit(*variable); } S::Void S::GUI::Arrows::OnChangeSize(const Size &nSize) { arrow1Hotspot->SetSize(nSize - Size(4 + (subtype == OR_HORZ ? GetWidth() / 2 : 0), 4 + (subtype == OR_HORZ ? 0 : GetHeight() / 2))); arrow2Hotspot->SetSize(nSize - Size(4 + (subtype == OR_HORZ ? GetWidth() / 2 : 0), 4 + (subtype == OR_HORZ ? 0 : GetHeight() / 2))); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/button.cpp000077500000000000000000000116111516402577000247520ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::Button::classID = S::Object::RequestClassID(); S::GUI::Button::Button(const String &iText, const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { type = classID; text = iText; if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(22); ComputeTextSize(); hotspot = new HotspotSimpleButton(flags & BF_NOFRAME ? Point() : Point(4, 4), GetSize() - (flags & BF_NOFRAME ? Size() : Size(8, 8))); hotspot->onLeftButtonClick.Connect(&onAction); Add(hotspot); onChangeSize.Connect(&Button::OnChangeSize, this); } S::GUI::Button::Button(const Bitmap &iBitmap, const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { type = classID; SetBitmap(iBitmap); if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(22); hotspot = new HotspotSimpleButton(flags & BF_NOFRAME ? Point() : Point(4, 4), GetSize() - (flags & BF_NOFRAME ? Size() : Size(8, 8))); hotspot->onLeftButtonClick.Connect(&onAction); Add(hotspot); onChangeSize.Connect(&Button::OnChangeSize, this); } S::GUI::Button::Button(const String &iText, const Bitmap &iBitmap, const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { type = classID; text = iText; SetBitmap(iBitmap); if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(22); ComputeTextSize(); hotspot = new HotspotSimpleButton(flags & BF_NOFRAME ? Point() : Point(4, 4), GetSize() - (flags & BF_NOFRAME ? Size() : Size(8, 8))); hotspot->onLeftButtonClick.Connect(&onAction); Add(hotspot); onChangeSize.Connect(&Button::OnChangeSize, this); } S::GUI::Button::~Button() { DeleteObject(hotspot); } S::Int S::GUI::Button::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); if (!(flags & BF_NOFRAME)) { surface->Frame(frame, FRAME_DOWN); surface->Frame(Rect(GetRealPosition() + Point(1, 1), GetRealSize() - Size(2, 2)), FRAME_UP); } if (text != NIL) { Rect textRect; textRect.left = frame.left + ((frame.GetWidth() - scaledTextSize.cx) / 2); if (bitmap != NIL) textRect.left = frame.left + ((frame.GetWidth() - scaledTextSize.cx - bitmap.GetSize().cx - 7) / 2) + bitmap.GetSize().cx + 7; textRect.top = frame.top + Math::Ceil(Float(frame.GetHeight() - scaledTextSize.cy) / 2) - 1; textRect.right = textRect.left + scaledTextSize.cx + 1; textRect.bottom = textRect.top + Math::Round(scaledTextSize.cy * 1.2); Font nFont = font; if (!IsActive()) nFont.SetColor(Setup::InactiveTextColor); surface->Box(textRect, GetBackgroundColor(), Rect::Filled); surface->SetText(text, textRect, nFont); } if (bitmap != NIL) { Size size = GetSize(); Size bmpSize = bitmap.GetSize(); if (Float(bmpSize.cx) / size.cx >= Float(bmpSize.cy) / size.cy && bmpSize.cx > size.cx - 12) bmpSize = bmpSize * (Float(size.cx - 12) / bmpSize.cx); else if (Float(bmpSize.cy) / size.cy >= Float(bmpSize.cx) / size.cx && bmpSize.cy > size.cy - 12) bmpSize = bmpSize * (Float(size.cy - 12) / bmpSize.cy); bmpSize = bmpSize * surface->GetSurfaceDPI() / 96.0; Rect bmpRect; bmpRect.left = frame.left + (frame.GetWidth() - bmpSize.cx) / 2; if (text != NIL) bmpRect.left = frame.left + (frame.GetWidth() - bmpSize.cx - scaledTextSize.cx - 7) / 2; bmpRect.top = frame.top + (frame.GetHeight() - bmpSize.cy) / 2; bmpRect.right = bmpRect.left + bmpSize.cx; bmpRect.bottom = bmpRect.top + bmpSize.cy; if (IsActive()) { surface->BlitFromBitmap(bitmap, Rect(Point(0, 0), bitmap.GetSize()), bmpRect); } else { Bitmap graymap(bitmap); graymap.GrayscaleBitmap(); surface->BlitFromBitmap(graymap, Rect(Point(0, 0), bitmap.GetSize()), bmpRect); } } } break; } return Success(); } S::Void S::GUI::Button::OnChangeSize(const Size &nSize) { hotspot->SetSize(nSize - (flags & BF_NOFRAME ? Size() : Size(8, 8))); } S::Int S::GUI::Button::SetBitmap(const Bitmap &nBitmap) { Bool prevVisible = IsVisible(); if (IsRegistered() && prevVisible) Hide(); bitmap = nBitmap; if (IsRegistered() && prevVisible) Show(); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/checkbox.cpp000077500000000000000000000103611516402577000252260ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::CheckBox::classID = S::Object::RequestClassID(); S::Signal0 S::GUI::CheckBox::internalCheckValues; S::GUI::CheckBox::CheckBox(const String &iText, const Point &iPos, const Size &iSize, Bool *iVariable) : Widget(iPos, iSize) { type = classID; text = iText; dummyVariable = False; if (iVariable == NIL) variable = &dummyVariable; else variable = iVariable; state = *variable; if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(17); ComputeTextSize(); internalCheckValues.Connect(&CheckBox::InternalCheckValues, this); hotspot = new HotspotSimpleButton(Point(0, 0), GetSize()); hotspot->onLeftButtonClick.Connect(&CheckBox::OnLeftButtonClick, this); hotspot->onLeftButtonClick.Connect(&onAction); onChangeSize.Connect(&HotspotSimpleButton::SetSize, hotspot); Add(hotspot); } S::GUI::CheckBox::~CheckBox() { DeleteObject(hotspot); internalCheckValues.Disconnect(&CheckBox::InternalCheckValues, this); } S::Int S::GUI::CheckBox::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: case SP_UPDATE: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->StartPaint(frame); if (message == SP_PAINT) { Font nFont = font; if (!IsActive()) nFont.SetColor(Setup::InactiveTextColor); surface->Box(frame, GetBackgroundColor(), Rect::Filled); surface->SetText(text, frame + Point(frame.GetHeight(), Math::Ceil(Float(frame.GetHeight() - scaledTextSize.cy) / 2) - 1), nFont); } Rect valueFrame = Rect(GetRealPosition() + Point(3, 3) * surface->GetSurfaceDPI() / 96.0, Size(frame.GetHeight(), frame.GetHeight()) - (Size(3, 3) * surface->GetSurfaceDPI() / 96.0) * 2); if (IsActive()) surface->Box(valueFrame, Setup::ClientColor, Rect::Filled); else surface->Box(valueFrame, Setup::BackgroundColor, Rect::Filled); surface->Frame(valueFrame, FRAME_DOWN); if (*variable == True) { Point p1 = Point(valueFrame.left + 3 - (IsRightToLeft() ? 1 : 0), valueFrame.top + 3); Point p2 = Point(valueFrame.right - 1 - (IsRightToLeft() ? 1 : 0), valueFrame.bottom - 1); for (Int i = 0; i < 2; i++) { Int color = IsActive() ? Setup::DividerDarkColor : Setup::DividerDarkColor.Average(Setup::BackgroundColor); if (i == 1) { color = IsActive() ? Setup::ClientTextColor : Setup::InactiveTextColor; p1 -= Point((IsRightToLeft() ? -i : i), i); p2 -= Point((IsRightToLeft() ? -i : i), i); } surface->Line(p1 + Point(0, 0), p2 - Point(0, 0), color); surface->Line(p1 + Point(1, 0), p2 - Point(0, 1), color); surface->Line(p1 + Point(0, 1), p2 - Point(1, 0), color); surface->Line(p1 + Point(valueFrame.GetWidth() - 5, 0), p2 - Point(valueFrame.GetWidth() - 3, 0), color); surface->Line(p1 + Point(valueFrame.GetWidth() - 5, 1), p2 - Point(valueFrame.GetWidth() - 4, 0), color); surface->Line(p1 + Point(valueFrame.GetWidth() - 6, 0), p2 - Point(valueFrame.GetWidth() - 3, 1), color); } } surface->EndPaint(); } break; } return Success(); } S::Int S::GUI::CheckBox::SetChecked(Bool newValue) { *variable = newValue; if (*variable != state) internalCheckValues.Emit(); return Success(); } S::Void S::GUI::CheckBox::OnLeftButtonClick() { if (*variable == False) *variable = True; else *variable = False; internalCheckValues.Emit(); } S::Void S::GUI::CheckBox::InternalCheckValues() { if (state != *variable) { state = *variable; Paint(SP_UPDATE); } } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/client.cpp000077500000000000000000000055321516402577000247220ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include const S::Short S::GUI::Client::classID = S::Object::RequestClassID(); S::GUI::Client::Client() : Widget(Point(), Size()) { type = classID; orientation = OR_CENTER; onPaint.SetParentObject(this); } S::GUI::Client::~Client() { } S::Int S::GUI::Client::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect client = Rect(GetRealPosition() + Point(2, 2), GetRealSize() - Size(3, 3)); for (Int i = Object::GetNOfObjects() - 1; i >= 0; i--) { Object *object = Object::GetNthObject(i); if (object == NIL || object->GetObjectType() != Divider::classID || ((Widget *) object)->GetContainer() != container) continue; /* Restrict size to area limited by dividers. */ Divider *divider = (Divider *) object; if (Binary::IsFlagSet(divider->GetFlags(), OR_VERT)) { Int dbPos = Math::Round(divider->GetX() * surface->GetSurfaceDPI() / 96.0); if ( Binary::IsFlagSet(divider->GetFlags(), OR_LEFT) && dbPos >= client.left - 3) client.left = dbPos + 4; else if (!Binary::IsFlagSet(divider->GetFlags(), OR_LEFT) && dbPos <= client.right + 1) client.right = container->GetWidth() - dbPos - 2; } else if (Binary::IsFlagSet(divider->GetFlags(), OR_HORZ)) { Int dbPos = Math::Round(divider->GetY() * surface->GetSurfaceDPI() / 96.0); if ( Binary::IsFlagSet(divider->GetFlags(), OR_TOP) && dbPos >= client.top - 2) client.top = dbPos + 4; else if (!Binary::IsFlagSet(divider->GetFlags(), OR_TOP) && dbPos <= client.bottom + 1) client.bottom = container->GetHeight() - dbPos - 2; } } Rect updateRect = container->GetContainerWindow()->GetUpdateRect(); switch (message) { case SP_PAINT: if (Rect::DoRectsOverlap(updateRect, client) || (updateRect.left == 0 && updateRect.top == 0 && updateRect.right == 0 && updateRect.bottom == 0)) { updateRect.right += 5; updateRect.bottom += 5; Rect intersectRect = Rect::OverlapRect(updateRect, client); surface->Box(intersectRect, Setup::ClientColor, Rect::Filled); surface->Box(client - Size(1, 1), Setup::DividerDarkColor, Rect::Outlined); onPaint.Emit(); } break; } return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/divider.cpp000077500000000000000000000141141516402577000250660ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::Divider::classID = S::Object::RequestClassID(); S::GUI::Divider::Divider(Int iPosition, Int iOrientation) : Widget(Point(), Size()) { type = classID; flags = iOrientation; orientation = OR_FREE; position = iPosition; dragging = False; startPos = 0; if (position == 0) position = 120; dragHotspot = new Hotspot(Point(), Size()); dragHotspot->SetIndependent(True); dragHotspot->onMouseOver.Connect(&Divider::OnMouseOver, this); dragHotspot->onMouseOut.Connect(&Divider::OnMouseOut, this); dragHotspot->onMouseDragStart.Connect(&Divider::OnMouseDragStart, this); dragHotspot->onMouseDrag.Connect(&Divider::OnMouseDrag, this); dragHotspot->onMouseDragEnd.Connect(&Divider::OnMouseDragEnd, this); Add(dragHotspot); } S::GUI::Divider::~Divider() { DeleteObject(dragHotspot); } S::Int S::GUI::Divider::SetPos(Int nPosition) { Bool prevVisible = IsVisible(); if (IsRegistered() && prevVisible) Hide(); position = nPosition; if (IsRegistered() && prevVisible) Show(); return Success(); } S::Int S::GUI::Divider::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { UpdateMetrics(); Surface *surface = GetDrawSurface(); Rect rect = Rect(GetRealPosition(), GetRealSize()); if (Binary::IsFlagSet(flags, OR_VERT)) surface->Bar(rect.GetPosition(), Point(rect.left, rect.bottom - 1), OR_VERT); else surface->Bar(rect.GetPosition(), Point(rect.right - 1, rect.top ), OR_HORZ); } break; } return Success(); } S::Void S::GUI::Divider::UpdateMetrics() { Window *wnd = GetContainerWindow(); Rect rect; if (wnd == NIL) return; if (Binary::IsFlagSet(flags, OR_VERT)) { Bool afterMe = False; if (container->GetObjectType() == Window::classID) { if (Binary::IsFlagSet(flags, OR_RIGHT)) rect.left = ((Window *) container)->GetClientRect().right - position; else rect.left = ((Window *) container)->GetClientRect().left + position; rect.top = wnd->GetClientRect().top; rect.bottom = wnd->GetClientRect().bottom; } else { if (Binary::IsFlagSet(flags, OR_RIGHT)) rect.left = container->GetWidth() - position; else rect.left = position; rect.top = 3; rect.bottom = container->GetHeight() - 3; } rect.right = rect.left + 2; for (Int i = container->GetNOfObjects() - 1; i >= 0; i--) { if (container->GetNthObject(i)->GetObjectType() != classID) continue; Divider *divider = (Divider *) container->GetNthObject(i); if (afterMe && !Binary::IsFlagSet(divider->flags, OR_VERT)) { if (Binary::IsFlagSet(divider->flags, OR_BOTTOM)) { if (container->GetHeight() - divider->GetY() <= rect.bottom + 1) rect.bottom = container->GetHeight() - divider->GetY() - 2; } else { if (divider->GetY() >= rect.top - 2) rect.top = divider->GetY() + 3; } } if (divider == this) afterMe = True; } } else { Bool afterMe = False; if (container->GetObjectType() == Window::classID) { if (Binary::IsFlagSet(flags, OR_BOTTOM)) rect.top = ((Window *) container)->GetClientRect().bottom - position; else rect.top = ((Window *) container)->GetClientRect().top + position; rect.left = wnd->GetClientRect().left; rect.right = wnd->GetClientRect().right; } else { if (Binary::IsFlagSet(flags, OR_BOTTOM)) rect.top = container->GetHeight() - position; else rect.top = position; rect.left = 3; rect.right = container->GetWidth() - 3; } rect.bottom = rect.top + 2; for (Int i = container->GetNOfObjects() - 1; i >= 0; i--) { if (container->GetNthObject(i)->GetObjectType() != classID) continue; Divider *divider = (Divider *) container->GetNthObject(i); if (afterMe && Binary::IsFlagSet(divider->flags, OR_VERT)) { if (Binary::IsFlagSet(divider->flags, OR_RIGHT)) { if (container->GetWidth() - divider->GetX() <= rect.right + 1) rect.right = container->GetWidth() - divider->GetX() - 2; } else { if (divider->GetX() >= rect.left - 2) rect.left = divider->GetX() + 3; } } if (divider == this) afterMe = True; } } SetMetrics(rect.GetPosition(), rect.GetSize()); if (Binary::IsFlagSet(flags, OR_VERT)) dragHotspot->SetMetrics(Point(-1, 0), rect.GetSize() + Size(2, 1)); else dragHotspot->SetMetrics(Point(0, -1), rect.GetSize() + Size(1, 2)); } S::Void S::GUI::Divider::OnMouseOver() { if (!Binary::IsFlagSet(flags, DIV_MOVABLE)) return; if (Binary::IsFlagSet(flags, OR_VERT)) Input::Pointer::SetCursor(container->GetContainerWindow(), Input::Pointer::CursorHSize); else Input::Pointer::SetCursor(container->GetContainerWindow(), Input::Pointer::CursorVSize); } S::Void S::GUI::Divider::OnMouseOut() { if (!Binary::IsFlagSet(flags, DIV_MOVABLE)) return; if (!dragging) Input::Pointer::SetCursor(container->GetContainerWindow(), Input::Pointer::CursorArrow); } S::Void S::GUI::Divider::OnMouseDragStart(const Point &mousePos) { dragging = True; startPos = GetPos(); startMousePos = mousePos; } S::Void S::GUI::Divider::OnMouseDrag(const Point &mousePos) { Int pos = startPos; if (Binary::IsFlagSet(flags, OR_VERT)) pos -= (startMousePos.x - mousePos.x); else pos -= (startMousePos.y - mousePos.y); if (pos != GetPos()) onDrag.Emit(pos); } S::Void S::GUI::Divider::OnMouseDragEnd(const Point &mousePos) { dragging = False; if (!dragHotspot->IsMouseOver()) Input::Pointer::SetCursor(container->GetContainerWindow(), Input::Pointer::CursorArrow); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/editbox.cpp000077500000000000000000000106731516402577000251040ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include const S::Short S::GUI::EditBox::classID = S::Object::RequestClassID(); S::GUI::EditBox::EditBox(const Point &iPos, const Size &iSize, Int maxSize) : Widget(iPos, iSize) { type = classID; dropDownList = NIL; comboBox = NIL; font.SetColor(Setup::ClientTextColor); if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(19); cursor = new Cursor(Point(3, Math::Ceil(Float(GetHeight() - font.GetUnscaledTextSizeY()) / 2) - 2), GetSize() - Size(6, Math::Ceil(Float(GetHeight() - font.GetUnscaledTextSizeY()) / 2) - 1)); cursor->SetMaxSize(maxSize); cursor->SetBackgroundColor(Setup::ClientColor); cursor->SetFont(font); cursor->onInput.Connect(&onInput); cursor->onEnter.Connect(&onEnter); Add(cursor); onInput.SetParentObject(this); onEnter.SetParentObject(this); onChangeSize.Connect(&EditBox::OnChangeSize, this); onLoseFocus.Connect(&cursor->onLoseFocus); } S::GUI::EditBox::EditBox(const String &iText, const Point &iPos, const Size &iSize, Int maxSize) : Widget(iPos, iSize) { type = classID; dropDownList = NIL; comboBox = NIL; font.SetColor(Setup::ClientTextColor); if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(19); cursor = new Cursor(Point(3, Math::Ceil(Float(GetHeight() - font.GetUnscaledTextSizeY()) / 2) - 2), GetSize() - Size(6, Math::Ceil(Float(GetHeight() - font.GetUnscaledTextSizeY()) / 2) - 1)); cursor->SetMaxSize(maxSize); cursor->SetBackgroundColor(Setup::ClientColor); cursor->SetFont(font); cursor->SetText(iText); cursor->onInput.Connect(&onInput); cursor->onEnter.Connect(&onEnter); Add(cursor); onInput.SetParentObject(this); onEnter.SetParentObject(this); onChangeSize.Connect(&EditBox::OnChangeSize, this); onLoseFocus.Connect(&cursor->onLoseFocus); } S::GUI::EditBox::~EditBox() { DeleteObject(cursor); if (comboBox != NIL) DeleteObject(comboBox); } S::Int S::GUI::EditBox::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Color backgroundColor = IsActive() ? Setup::ClientColor : Setup::BackgroundColor; surface->StartPaint(GetVisibleArea()); cursor->SetBackgroundColor(backgroundColor); surface->Box(frame, backgroundColor, Rect::Filled); surface->Frame(frame, FRAME_DOWN); Widget::Paint(message); surface->EndPaint(); return Success(); } } return Widget::Paint(message); } S::Int S::GUI::EditBox::SetDropDownList(List *nDropDownList) { Surface *surface = GetDrawSurface(); surface->StartPaint(GetVisibleArea()); if (comboBox != NIL) DeleteObject(comboBox); dropDownList = nDropDownList; if (dropDownList != NIL) { comboBox = new ComboBox(Point(), Size()); comboBox->SetFlags(CB_HOTSPOTONLY); comboBox->onSelectEntry.Connect(&EditBox::OnSelectEntry, this); for (Int i = 0; i < dropDownList->Length(); i++) { if (dropDownList->GetNthEntry(i)->GetObjectType() == ListEntrySeparator::classID) comboBox->AddSeparator(); else comboBox->AddEntry(dropDownList->GetNthEntry(i)->GetText()); } Add(comboBox); OnChangeSize(GetSize()); } Paint(SP_PAINT); surface->EndPaint(); return Success(); } S::Void S::GUI::EditBox::OnSelectEntry(ListEntry *entry) { cursor->SetText(entry->GetText()); cursor->MarkAll(); onSelectEntry.Emit(entry); onInput.Emit(cursor->GetText()); } S::Void S::GUI::EditBox::OnChangeSize(const Size &nSize) { cursor->SetMetrics(Point(3, Math::Ceil(Float(nSize.cy - font.GetUnscaledTextSizeY()) / 2) - 2), nSize - Size(6 + (comboBox != NIL ? 17 : 0), Math::Ceil(Float(nSize.cy - font.GetUnscaledTextSizeY()) / 2) - 1)); if (comboBox != NIL) comboBox->SetSize(nSize); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/groupbox.cpp000077500000000000000000000050651516402577000253120ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::GUI::GroupBox::classID = S::Object::RequestClassID(); S::GUI::GroupBox::GroupBox(const String &iText, const Point &iPos, const Size &iSize) : Layer(iText) { type = classID; orientation = OR_UPPERLEFT; SetMetrics(iPos, iSize); if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(80); ComputeTextSize(); } S::GUI::GroupBox::~GroupBox() { } S::Int S::GUI::GroupBox::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->Frame(frame, FRAME_DOWN); surface->Frame(frame + Point(1, 1) - Size(2, 2), FRAME_UP); Rect textRect = Rect(GetRealPosition() + Point(10 * surface->GetSurfaceDPI() / 96.0, -Math::Ceil(Float(scaledTextSize.cy) / 2)), Size(scaledTextSize.cx, Math::Round(scaledTextSize.cy * 1.2)) + Size(3, 0) * surface->GetSurfaceDPI() / 96.0); surface->Box(textRect, Setup::BackgroundColor, Rect::Filled); Font nFont = font; if (!IsActive()) nFont.SetColor(Setup::InactiveTextColor); surface->SetText(text, textRect + Point(1, 0) * surface->GetSurfaceDPI() / 96.0, nFont); } break; } return Layer::Paint(message); } S::Int S::GUI::GroupBox::Activate() { if (active) return Success(); active = True; Paint(SP_PAINT); onActivate.Emit(); return Success(); } S::Int S::GUI::GroupBox::Deactivate() { if (!active) return Success(); active = False; Paint(SP_PAINT); onDeactivate.Emit(); return Success(); } S::Int S::GUI::GroupBox::Show() { Int retVal = Layer::Show(); Paint(SP_PAINT); return retVal; } S::Int S::GUI::GroupBox::Hide() { if (IsRegistered() && IsVisible()) { Surface *surface = GetDrawSurface(); surface->Box(Rect(GetRealPosition() - Point(0, 6) * surface->GetSurfaceDPI() / 96.0, GetRealSize() + Size(0, 6) * surface->GetSurfaceDPI() / 96.0), Setup::BackgroundColor, Rect::Filled); } return Layer::Hide(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/hyperlink.cpp000077500000000000000000000067711516402577000254570ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include const S::Short S::GUI::Hyperlink::classID = S::Object::RequestClassID(); S::GUI::Hyperlink::Hyperlink(const String &iText, const String &iLink, const Point &iPos) : Text(iText, iPos, Size()) { type = classID; linkURL = iLink; font.SetColor(Setup::LinkColor); ComputeTextSize(); SetSize(scaledTextSize * 96.0 / Surface().GetSurfaceDPI() + Size(0, 2)); hotspot = new Hotspot(Point(0, 0), GetSize()); hotspot->onMouseOver.Connect(&Hyperlink::OnMouseOver, this); hotspot->onMouseOut.Connect(&Hyperlink::OnMouseOut, this); hotspot->onLeftButtonClick.Connect(&Hyperlink::OnClickLink, this); Add(hotspot); } S::GUI::Hyperlink::Hyperlink(const Bitmap &iBitmap, const String &iLink, const Point &iPos, const Size &iSize) : Text(NIL, iPos, Size()) { type = classID; linkURL = iLink; SetSize(iSize); SetBitmap(iBitmap); if (GetSize() == Size(0, 0)) SetSize(linkBitmap.GetSize()); hotspot = new Hotspot(Point(0, 0), GetSize()); hotspot->onMouseOver.Connect(&Hyperlink::OnMouseOver, this); hotspot->onMouseOut.Connect(&Hyperlink::OnMouseOut, this); hotspot->onLeftButtonClick.Connect(&Hyperlink::OnClickLink, this); Add(hotspot); } S::GUI::Hyperlink::~Hyperlink() { DeleteObject(hotspot); } S::Int S::GUI::Hyperlink::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: if (linkBitmap != NIL) { Rect rect = Rect(GetRealPosition(), GetRealSize()); Surface *surface = GetDrawSurface(); surface->BlitFromBitmap(linkBitmap, Rect(Point(0, 0), linkBitmap.GetSize()), rect); } break; } return Text::Paint(message); } S::Void S::GUI::Hyperlink::OnMouseOver() { Input::Pointer::SetCursor(container->GetContainerWindow(), Input::Pointer::CursorHand); if (linkBitmap == NIL) { Font originalFont = font; font.SetColor(Setup::LinkHighlightColor); if (Setup::LinkHighlightColor == Setup::LinkColor) font.SetStyle(Font::Underline); Text::Paint(SP_PAINT); font.SetColor(originalFont.GetColor()); font.SetStyle(originalFont.GetStyle()); } } S::Void S::GUI::Hyperlink::OnMouseOut() { Input::Pointer::SetCursor(container->GetContainerWindow(), Input::Pointer::CursorArrow); if (linkBitmap == NIL) { Text::Paint(SP_PAINT); } } S::Void S::GUI::Hyperlink::OnClickLink() { S::System::System::OpenURL(linkURL); onAction.Emit(); } S::Int S::GUI::Hyperlink::SetText(const String &nText) { if (linkBitmap != NIL) linkBitmap = NIL; Text::SetText(nText); hotspot->SetSize(GetSize()); return Success(); } S::Int S::GUI::Hyperlink::SetFont(const Font &nFont) { Text::SetFont(nFont); hotspot->SetSize(GetSize()); return Success(); } S::Int S::GUI::Hyperlink::SetBitmap(const Bitmap &newBitmap) { linkBitmap = newBitmap; Paint(SP_PAINT); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/image.cpp000077500000000000000000000045201516402577000245220ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include const S::Short S::GUI::Image::classID = S::Object::RequestClassID(); S::GUI::Image::Image(const Bitmap &iBitmap, const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { type = classID; SetBitmap(iBitmap); } S::GUI::Image::~Image() { } S::Int S::GUI::Image::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); /* Scale image if necessary. */ Size size = GetSize(); Size bmpSize = bitmap.GetSize(); Size newSize = bmpSize; if (Float(bmpSize.cx) / size.cx >= Float(bmpSize.cy) / size.cy && bmpSize.cx > size.cx) newSize = newSize * (Float(size.cx) / bmpSize.cx); else if (Float(bmpSize.cy) / size.cy >= Float(bmpSize.cx) / size.cx && bmpSize.cy > size.cy) newSize = newSize * (Float(size.cy) / bmpSize.cy); newSize = newSize * surface->GetSurfaceDPI() / 96.0; /* Draw image centered. */ Size realSize = GetRealSize(); Rect bmpRect = Rect(GetRealPosition() + Point(realSize.cx - newSize.cx, realSize.cy - newSize.cy) / 2, newSize); surface->StartPaint(GetVisibleArea()); if (bmpSize != newSize && bitmapScaled.GetSize() != newSize) bitmapScaled = bitmap.Scale(newSize); if (bmpSize == newSize) surface->BlitFromBitmap(bitmap, Rect(Point(0, 0), bmpSize), bmpRect); else surface->BlitFromBitmap(bitmapScaled, Rect(Point(0, 0), newSize), bmpRect); surface->EndPaint(); } break; } return Success(); } S::Int S::GUI::Image::SetBitmap(const Bitmap &newBmp) { if (bitmap == newBmp) return Success(); Bool prevVisible = IsVisible(); if (prevVisible) Hide(); bitmap = newBmp; bitmapScaled = NIL; if (GetSize() == Size(0, 0)) SetSize(bitmap.GetSize()); if (prevVisible) Show(); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/multiedit.cpp000077500000000000000000000115401516402577000254400ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include const S::Short S::GUI::MultiEdit::classID = S::Object::RequestClassID(); S::GUI::MultiEdit::MultiEdit(const Point &iPos, const Size &iSize, Int maxSize) : Widget(iPos, iSize) { type = classID; scrollbar = NIL; scrollbarPos = 0; font.SetColor(Setup::ClientTextColor); if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(19); cursor = new Cursor(Point(3, Math::Ceil(Float(19 - font.GetUnscaledTextSizeY()) / 2) - 2), GetSize() - Size(6, Math::Ceil(Float(19 - font.GetUnscaledTextSizeY()) / 2) - 1)); cursor->onScroll.Connect(&MultiEdit::OnCursorScroll, this); cursor->SetMaxSize(maxSize); cursor->SetBackgroundColor(Setup::ClientColor); cursor->SetFlags(CF_MULTILINE); cursor->SetFont(font); cursor->onInput.Connect(&onInput); Add(cursor); onInput.SetParentObject(this); onChangeSize.Connect(&MultiEdit::OnChangeSize, this); onLoseFocus.Connect(&cursor->onLoseFocus); } S::GUI::MultiEdit::MultiEdit(const String &iText, const Point &iPos, const Size &iSize, Int maxSize) : Widget(iPos, iSize) { type = classID; scrollbar = NIL; scrollbarPos = 0; font.SetColor(Setup::ClientTextColor); if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(19); cursor = new Cursor(Point(3, Math::Ceil(Float(19 - font.GetUnscaledTextSizeY()) / 2) - 2), GetSize() - Size(6, Math::Ceil(Float(19 - font.GetUnscaledTextSizeY()) / 2) - 1)); cursor->onScroll.Connect(&MultiEdit::OnCursorScroll, this); cursor->SetMaxSize(maxSize); cursor->SetBackgroundColor(Setup::ClientColor); cursor->SetFlags(CF_MULTILINE); cursor->SetFont(font); cursor->SetText(iText); cursor->onInput.Connect(&onInput); Add(cursor); onInput.SetParentObject(this); onChangeSize.Connect(&MultiEdit::OnChangeSize, this); onLoseFocus.Connect(&cursor->onLoseFocus); } S::GUI::MultiEdit::~MultiEdit() { DeleteObject(cursor); if (scrollbar != NIL) DeleteObject(scrollbar); } S::Int S::GUI::MultiEdit::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Color backgroundColor = IsActive() ? Setup::ClientColor : Setup::BackgroundColor; surface->StartPaint(GetVisibleArea()); cursor->SetBackgroundColor(backgroundColor); surface->Box(frame, backgroundColor, Rect::Filled); surface->Frame(frame, FRAME_DOWN); Widget::Paint(message); surface->EndPaint(); return Success(); } } return Widget::Paint(message); } S::Int S::GUI::MultiEdit::GetNOfLines() { Int lines = 1; Int length = text.Length(); for (Int i = 0; i < length; i++) { if (text[i] == '\n') lines++; } return lines; } S::Int S::GUI::MultiEdit::GetNOfInvisibleLines() { static Int lineSize = font.GetUnscaledTextSizeY() + 1; return 1 + GetNOfLines() - Math::Floor((GetHeight() - 6) / lineSize); } S::Int S::GUI::MultiEdit::SetText(const String &newText) { scrollbarPos = 0; cursor->SetVisibleDirect(False); cursor->SetText(newText); cursor->SetVisibleDirect(True); if (IsVisible()) Paint(SP_PAINT); return Success(); } S::Void S::GUI::MultiEdit::OnScroll() { cursor->Scroll(scrollbarPos); } S::Void S::GUI::MultiEdit::OnCursorScroll(Int scrollPos, Int maxScrollPos) { if (maxScrollPos == 0 && scrollbar != NIL) { DeleteObject(scrollbar); scrollbar = NIL; cursor->SetWidth(cursor->GetWidth() + 17); Paint(SP_PAINT); } else if (scrollbar == NIL) { cursor->SetWidth(cursor->GetWidth() - 17); scrollbar = new Scrollbar(Point(18, 1), Size(0, GetHeight() - 2), OR_VERT, &scrollbarPos, 0, maxScrollPos); scrollbar->onValueChange.Connect(&MultiEdit::OnScroll, this); scrollbar->SetOrientation(OR_UPPERRIGHT); scrollbar->SetAlwaysActive(True); Add(scrollbar); Paint(SP_PAINT); } else { scrollbar->SetRange(0, maxScrollPos); scrollbar->SetValue(scrollPos); } } S::Void S::GUI::MultiEdit::OnChangeSize(const Size &nSize) { if (scrollbar != NIL) scrollbar->SetHeight(nSize.cy - 2); cursor->SetSize(nSize - Size(6 + (scrollbar != NIL ? 17 : 0), Math::Ceil(Float(19 - font.GetUnscaledTextSizeY()) / 2) - 1)); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/optionbox.cpp000077500000000000000000000117661516402577000254730ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::OptionBox::classID = S::Object::RequestClassID(); S::Signal0 S::GUI::OptionBox::internalCheckValues; S::GUI::OptionBox::OptionBox(const String &iText, const Point &iPos, const Size &iSize, Int *var, Int iCode) : Widget(iPos, iSize) { type = classID; text = iText; variable = var; code = iCode; if (*variable == code) state = True; else state = False; if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(17); ComputeTextSize(); internalCheckValues.Connect(&OptionBox::InternalCheckValues, this); hotspot = new HotspotSimpleButton(Point(0, 0), GetSize()); hotspot->onLeftButtonClick.Connect(&OptionBox::OnLeftButtonClick, this); hotspot->onLeftButtonClick.Connect(&onAction); onChangeSize.Connect(&HotspotSimpleButton::SetSize, hotspot); Add(hotspot); } S::GUI::OptionBox::~OptionBox() { DeleteObject(hotspot); internalCheckValues.Disconnect(&OptionBox::InternalCheckValues, this); } S::Int S::GUI::OptionBox::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: case SP_UPDATE: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->StartPaint(frame); if (message == SP_PAINT) { Font nFont = font; if (!IsActive()) nFont.SetColor(Setup::InactiveTextColor); surface->Box(frame, GetBackgroundColor(), Rect::Filled); surface->SetText(text, frame + Point(frame.GetHeight(), Math::Ceil(Float(frame.GetHeight() - scaledTextSize.cy) / 2) - 1), nFont); } Float scaleFactor = surface->GetSurfaceDPI() / 96.0; Int inset = 3 * scaleFactor; Point lineStart = Point(frame.left, frame.top) + Point(3, 3) * scaleFactor + Point(inset + (IsRightToLeft() ? 1 : 0), 0); Point lineEnd = lineStart + Point(11 * scaleFactor - 2 * inset, 0); Int lightColor = Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255)); Int darkColor = Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0)); Int innerColor = (IsActive() ? Setup::ClientColor : Setup::BackgroundColor); surface->Line(lineStart, lineEnd, darkColor); for (Int i = 0; i < Int(11 * scaleFactor) - 2; i++) { if (i < inset) { lineStart.x--; lineEnd.x++; } else if (i > (11 * scaleFactor) - 2 - inset) { lineStart.x++; lineEnd.x--; } lineStart.y++; lineEnd.y++; surface->Line(lineStart, lineEnd, innerColor); Int leftColor = (i > (11 * scaleFactor) - 2 - inset) ? lightColor : (IsRightToLeft() ? lightColor : darkColor); Int rightColor = (i > (11 * scaleFactor) - 2 - inset) ? lightColor : (IsRightToLeft() ? darkColor : lightColor); surface->SetPixel(lineStart, leftColor); surface->SetPixel(lineEnd - Point(1, 0), rightColor); } lineStart.x++; lineStart.y++; lineEnd.x--; lineEnd.y++; surface->Line(lineStart, lineEnd, lightColor); if (*variable == code) { for (Int i = 0; i < 2; i++) { Int color = IsActive() ? Setup::DividerDarkColor : Setup::DividerDarkColor.Average(Setup::BackgroundColor); Point offset = Point(IsRightToLeft() ? 0 : 1, 0); if (i == 1) { color = IsActive() ? Setup::ClientTextColor : Setup::InactiveTextColor; offset -= Point(IsRightToLeft() ? -i : i, i); } Int inset = 2 * scaleFactor; Point lineStart = Point(frame.left, frame.top) + Point(6, 6) * scaleFactor + offset + Point(inset, 0); Point lineEnd = lineStart + Point(5 * scaleFactor - 2 * inset, 0); for (Int j = 0; j < Int(5 * scaleFactor); j++) { if (j < inset) { lineStart.x--; lineEnd.x++; } else if (j > (5 * scaleFactor) - inset) { lineStart.x++; lineEnd.x--; } lineStart.y++; lineEnd.y++; surface->Line(lineStart, lineEnd, color); } } } surface->EndPaint(); } break; } return Success(); } S::Void S::GUI::OptionBox::OnLeftButtonClick() { *variable = code; internalCheckValues.Emit(); } S::Void S::GUI::OptionBox::InternalCheckValues() { state = (*variable == code ? True : False); Paint(SP_UPDATE); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/progressbar.cpp000077500000000000000000000123251516402577000257730ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::Progressbar::classID = S::Object::RequestClassID(); S::GUI::Progressbar::Progressbar(const Point &iPos, const Size &iSize, Int sType, Int iTextFlag, Int rangeStart, Int rangeEnd, Int iValue) : Widget(iPos, iSize) { type = classID; subtype = sType; startValue = rangeStart; endValue = rangeEnd; value = startValue; gradientDirection = 0; SetFlags(iTextFlag); SetValue(iValue); font.SetColor(Setup::ClientTextColor); if (GetWidth() == 0) SetWidth(subtype == OR_VERT ? 19 : 80); if (GetHeight() == 0) SetHeight(subtype == OR_VERT ? 80 : 19); } S::GUI::Progressbar::~Progressbar() { } S::Int S::GUI::Progressbar::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); switch (message) { case SP_PAINT: case SP_UPDATE: surface->StartPaint(GetVisibleArea()); if (IsActive()) surface->Box(frame + Point(1, 1) - Size(2, 2), Setup::ClientColor, Rect::Filled); else surface->Box(frame + Point(1, 1) - Size(2, 2), Setup::BackgroundColor, Rect::Filled); if (message != SP_UPDATE) surface->Frame(frame, FRAME_DOWN); if (value > 0) { Rect frame = Rect(GetRealPosition(), GetRealSize()) + Point(1, 1) - Size(2, 2); if (subtype == OR_HORZ) frame.right = frame.left + (Int) (frame.GetWidth() / ((Float) (endValue - startValue) / (Float) (value - startValue))); else frame.top = frame.bottom - (Int) (frame.GetHeight() / ((Float) (endValue - startValue) / (Float) (value - startValue))); /* Update gradient bitmap if necessary. */ if (gradient.GetSize() != GetRealSize() - Size(2, 2) || gradientDirection != IsRightToLeft()) CreateGradient(GetRealSize()); gradient.BlitToSurface(Rect(Point(0 + (IsRightToLeft() ? gradient.GetSize().cx - frame.GetWidth() : 0), 0), frame.GetSize()), surface, frame); } if (subtype == OR_HORZ) { I18n::Translator *i18n = I18n::Translator::defaultTranslator; switch (GetFlags()) { case PB_NOTEXT: break; case PB_VALUE: text = String::FromInt((Int) Math::Max(value, startValue)); break; case PB_PERCENT: if (value > 0) text = i18n->TranslateString("%1%").Replace("%1", String::FromInt((Int) Math::Max(0, (Int) Math::Round(100 / ((Float) (endValue - startValue) / (Float) (value - startValue)))))); else text = i18n->TranslateString("%1%").Replace("%1", "0"); break; } Point realPos = GetRealPosition(); Int textSize = font.GetScaledTextSizeX(text); Rect textRect = Rect(Point(realPos.x + (frame.GetWidth() - textSize) / 2, realPos.y + Math::Ceil(Float(frame.GetHeight() - font.GetScaledTextSizeY()) / 2) - 1), Size(textSize, frame.GetHeight() - Math::Round(2 * surface->GetSurfaceDPI() / 96.0) - 1)); surface->SetText(text, textRect, font); if (value > 0) { textRect.right = realPos.x + (Int) ((frame.GetWidth() - 2) / ((Float) (endValue - startValue) / (Float) (value - startValue))); Font nFont = font; nFont.SetColor(Setup::GradientTextColor); surface->SetText(text, textRect, nFont); } } surface->EndPaint(); break; } return Success(); } S::Void S::GUI::Progressbar::SetValue(Int newValue) { Int prevValue = value; value = (Int) Math::Min(endValue, Math::Max(startValue, newValue)); if (prevValue != value) Paint(SP_UPDATE); } S::Void S::GUI::Progressbar::CreateGradient(const Size &gSize) { gradient.CreateBitmap(gSize - Size(2, 2)); gradientDirection = IsRightToLeft(); Color startColor = IsRightToLeft() ? Setup::GradientEndColor : Setup::GradientStartColor; Color endColor = IsRightToLeft() ? Setup::GradientStartColor : Setup::GradientEndColor; Int rs = startColor.GetRed(); Int gs = startColor.GetGreen(); Int bs = startColor.GetBlue(); Float rp = ((Float) (endColor.GetRed() - rs)) / ((subtype == OR_HORZ) ? (gSize.cx - 2) : (gSize.cy - 2)); Float gp = ((Float) (endColor.GetGreen() - gs)) / ((subtype == OR_HORZ) ? (gSize.cx - 2) : (gSize.cy - 2)); Float bp = ((Float) (endColor.GetBlue() - bs)) / ((subtype == OR_HORZ) ? (gSize.cx - 2) : (gSize.cy - 2)); if (subtype == OR_HORZ) { for (Int x = 0; x < gSize.cx - 2; x++) { for (Int y = 0; y < gSize.cy - 2; y++) gradient.SetPixel(Point(x, y), Color((Int) (rs + rp * x), (Int) (gs + gp * x), (Int) (bs + bp * x))); } } else { for (Int y = 0; y < gSize.cy - 2; y++) { for (Int x = 0; x < gSize.cx - 2; x++) gradient.SetPixel(Point(x, gSize.cy - 3 - y), Color((Int) (rs + rp * y), (Int) (gs + gp * y), (Int) (bs + bp * y))); } } } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/scrollbar.cpp000077500000000000000000000243161516402577000254300ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include const S::Short S::GUI::Scrollbar::classID = S::Object::RequestClassID(); S::GUI::Scrollbar::Scrollbar(const Point &iPos, const Size &iSize, Int sType, Int *var, Int rangeStart, Int rangeEnd) : Arrows(iPos, iSize, sType, var, rangeStart, rangeEnd) { type = classID; if (GetWidth() == 0) SetWidth(subtype == OR_VERT ? 17 : 120); if (GetHeight() == 0) SetHeight(subtype == OR_VERT ? 120 : 17); clickHotspot = new Hotspot(Point(), Size()); dragHotspot = new Hotspot(Point(), Size()); clickTimer = new System::Timer(); clickTimerDirection = 1; pageSize = 6; dragging = False; clickOffset = 0; scrollSpill = 0; clickHotspot->onLeftButtonDown.Connect(&Scrollbar::OnMouseClick, this); clickHotspot->onLeftButtonUp.Connect(&System::Timer::Stop, clickTimer); clickHotspot->onMouseOut.Connect(&System::Timer::Stop, clickTimer); dragHotspot->onMouseDragStart.Connect(&Scrollbar::OnMouseDragStart, this); dragHotspot->onMouseDrag.Connect(&Scrollbar::OnMouseDrag, this); dragHotspot->onMouseDragEnd.Connect(&Scrollbar::OnMouseDragEnd, this); dragHotspot->onMouseWheel.Connect(&Scrollbar::OnMouseWheel, this); clickTimer->onInterval.Connect(&Scrollbar::OnMouseClickTimer, this); Add(clickHotspot); Add(dragHotspot); UpdateHotspotPositions(); onRangeChange.Connect(&Scrollbar::OnValueChange, this); onValueChange.Connect(&Scrollbar::OnValueChange, this); } S::GUI::Scrollbar::~Scrollbar() { DeleteObject(clickHotspot); DeleteObject(dragHotspot); DeleteObject(clickTimer); } S::Int S::GUI::Scrollbar::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Bool smallHotspots = (subtype == OR_HORZ && (GetWidth() <= 55)) || (subtype == OR_VERT && (GetHeight() <= 55)); Int hotspotSize = Math::Round((smallHotspots ? 10 : (subtype == OR_HORZ ? GetHeight() : GetWidth())) * surface->GetSurfaceDPI() / 96.0) - 4; Rect arrow1Frame = Rect(realPos + Point(subtype == OR_HORZ ? realSize.cx - (hotspotSize + 4) : 0, subtype == OR_VERT ? realSize.cy - (hotspotSize + 4) : 0), subtype == OR_HORZ ? Size(hotspotSize + 4, realSize.cy) : Size(realSize.cx, hotspotSize + 4)); Rect arrow2Frame = Rect(realPos + Point(0, 0), subtype == OR_HORZ ? Size(hotspotSize + 4, realSize.cy) : Size(realSize.cx, hotspotSize + 4)); Int arrowColor = Setup::TextColor; if (!IsActive()) arrowColor = Setup::InactiveTextColor; switch (message) { case SP_PAINT: surface->StartPaint(Rect(realPos, realSize)); OnValueChange(); surface->Box(arrow1Frame, Setup::BackgroundColor, Rect::Filled); surface->Box(arrow2Frame, Setup::BackgroundColor, Rect::Filled); surface->Frame(arrow1Frame, FRAME_UP); surface->Frame(arrow2Frame, FRAME_UP); if (subtype == OR_HORZ) { Int size = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); for (Int i = 0; i < size; i++) { Point lineStart = Point(realPos.x + (hotspotSize + 4) / 2 - size / 2 + i, realPos.y + realSize.cy / 2 - i); Point lineEnd = lineStart + Point(0, 2 * i + 1); surface->Line(lineStart, lineEnd, arrowColor); } for (Int i = 0; i < size; i++) { Point lineStart = Point(realPos.x + realSize.cx - (hotspotSize + 4) / 2 - (size + 1) / 2 + i, realPos.y + realSize.cy / 2 - size + 1 + i); Point lineEnd = lineStart + Point(0, 2 * (size - i) - 1); surface->Line(lineStart, lineEnd, arrowColor); } } else if (subtype == OR_VERT) { Int size = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); for (Int i = 0; i < size; i++) { Point lineStart = Point(realPos.x + realSize.cx / 2 + (IsRightToLeft() ? 1 : 0) - i, (realPos.y + (hotspotSize + 4) / 2) - size / 2 + i); Point lineEnd = lineStart + Point(2 * i + 1, 0); surface->Line(lineStart, lineEnd, arrowColor); } for (Int i = 0; i < size; i++) { Point lineStart = Point(realPos.x + realSize.cx / 2 + (IsRightToLeft() ? 1 : 0) - size + 1 + i, (realPos.y + realSize.cy - (hotspotSize + 4) / 2) - (size + 1) / 2 + i); Point lineEnd = lineStart + Point(2 * (size - i) - 1, 0); surface->Line(lineStart, lineEnd, arrowColor); } } surface->EndPaint(); break; } return Success(); } S::Void S::GUI::Scrollbar::OnMouseClick(const Point &mousePos) { if (dragHotspot->IsMouseOver()) return; Int value = 0; if (subtype == OR_HORZ) value = (mousePos.x < dragHotspot->GetRealPosition().x) ? -pageSize : pageSize; else value = (mousePos.y < dragHotspot->GetRealPosition().y) ? -pageSize : pageSize; if (clickTimer->GetStatus() == System::TIMER_STOPPED) { clickTimer->Start(250); clickTimerDirection = (value > 0 ? 1 : -1); } if (value / clickTimerDirection >= 0) SetValue(*variable + value); } S::Void S::GUI::Scrollbar::OnMouseClickTimer() { Window *window = container->GetContainerWindow(); OnMouseClick(window->GetMousePosition()); clickTimer->Restart(100); } S::Void S::GUI::Scrollbar::OnMouseWheel(Float value) { if (subtype != OR_VERT) return; Window *window = container->GetContainerWindow(); if (IsMouseOver() || window->IsMouseOn(Rect(container->GetRealPosition(), container->GetRealSize()))) { Surface *surface = GetDrawSurface(); surface->StartPaint(container->GetVisibleArea()); /* Reset spill value upon scroll direction change. */ if (Math::Sign(value) != Math::Sign(scrollSpill)) scrollSpill = 0; /* Update scroll position value. */ Int amount = (value + scrollSpill) * stepSize; SetValue(*variable - amount); scrollSpill += value - (Float(amount) / stepSize); /* Send an event to update widget under cursor if necessary. */ container->Process(SM_MOUSEMOVE, 0, 0); surface->EndPaint(); } } S::Void S::GUI::Scrollbar::OnMouseDragStart(const Point &mousePos) { if (subtype == OR_HORZ) clickOffset = mousePos.x - dragHotspot->GetRealPosition().x; else clickOffset = mousePos.y - dragHotspot->GetRealPosition().y; dragging = True; } S::Void S::GUI::Scrollbar::OnMouseDrag(const Point &mousePos) { Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Int value = 0; Surface *surface = GetDrawSurface(); Bool smallHotspots = (subtype == OR_HORZ && (GetWidth() <= 55)) || (subtype == OR_VERT && (GetHeight() <= 55)); Int hotspotSize = Math::Round((smallHotspots ? 10 : (subtype == OR_HORZ ? GetHeight() : GetWidth())) * surface->GetSurfaceDPI() / 96.0) - 4; if (subtype == OR_HORZ) value = Math::Round((((Float) (endValue - startValue)) / ((Float) realSize.cx - 3 * (hotspotSize + 4))) * ((Float) (mousePos.x - clickOffset - (realPos.x + hotspotSize + 4)))); else value = Math::Round((((Float) (endValue - startValue)) / ((Float) realSize.cy - 3 * (hotspotSize + 4))) * ((Float) (mousePos.y - clickOffset - (realPos.y + hotspotSize + 4)))); SetValue(startValue + value); } S::Void S::GUI::Scrollbar::OnMouseDragEnd(const Point &mousePos) { dragging = False; OnValueChange(); } S::Void S::GUI::Scrollbar::OnValueChange() { UpdateHotspotPositions(); if (!IsRegistered() || !IsVisible()) return; Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Bool smallHotspots = (subtype == OR_HORZ && (GetWidth() <= 55)) || (subtype == OR_VERT && (GetHeight() <= 55)); Int hotspotSize = Math::Round((smallHotspots ? 10 : (subtype == OR_HORZ ? GetHeight() : GetWidth())) * surface->GetSurfaceDPI() / 96.0) - 4; Rect backFrame = Rect(realPos + (subtype == OR_HORZ ? Point(hotspotSize + 4, 0) : Point(0, hotspotSize + 4)), realSize - (subtype == OR_HORZ ? Size(2 * (hotspotSize + 4), 0) : Size(0, 2 * (hotspotSize + 4)))); Rect sliderFrame = Rect(realPos + (subtype == OR_HORZ ? Point(hotspotSize + 4 + (Int) (((Float) realSize.cx - 3 * (hotspotSize + 4)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue))), 0) : Point(0, hotspotSize + 4 + (Int) (((Float) realSize.cy - 3 * (hotspotSize + 4)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue))))), subtype == OR_HORZ ? Size(hotspotSize + 4, realSize.cy) : Size(realSize.cx, hotspotSize + 4)); surface->StartPaint(backFrame); surface->Box(backFrame, Setup::LightGrayColor, Rect::Filled); if (!dragging) surface->Box(sliderFrame, Setup::BackgroundColor, Rect::Filled); surface->Frame(sliderFrame, FRAME_UP); surface->EndPaint(); } S::Void S::GUI::Scrollbar::UpdateHotspotPositions() { Bool smallHotspots = (subtype == OR_HORZ && (GetWidth() <= 55)) || (subtype == OR_VERT && (GetHeight() <= 55)); Int hotspotSize = (smallHotspots ? 10 : (subtype == OR_HORZ ? GetHeight() : GetWidth())) - 4; arrow1Hotspot->SetMetrics(Point(2 + (subtype == OR_HORZ ? GetWidth() - (hotspotSize + 4) : 0), 2 + (subtype == OR_VERT ? GetHeight() - (hotspotSize + 4) : 0)), subtype == OR_HORZ ? Size(hotspotSize, GetHeight() - 4) : Size(GetWidth() - 4, hotspotSize)); arrow2Hotspot->SetMetrics(Point(2, 2), subtype == OR_HORZ ? Size(hotspotSize, GetHeight() - 4) : Size(GetWidth() - 4, hotspotSize)); clickHotspot->SetMetrics(subtype == OR_HORZ ? Point(hotspotSize + 4, 0) : Point(0, hotspotSize + 4), GetSize() - (subtype == OR_HORZ ? Size(2 * (hotspotSize + 4), 0) : Size(0, 2 * (hotspotSize + 4)))); dragHotspot->SetMetrics(subtype == OR_HORZ ? Point(hotspotSize + 4 + (Int) (((Float) GetWidth() - 3 * (hotspotSize + 4)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue))), 0) : Point(0, hotspotSize + 4 + (Int) (((Float) GetHeight() - 3 * (hotspotSize + 4)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue)))), subtype == OR_HORZ ? Size(hotspotSize + 4, GetHeight()) : Size(GetWidth(), hotspotSize + 4)); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/slider.cpp000077500000000000000000000157241516402577000247320ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::Slider::classID = S::Object::RequestClassID(); S::GUI::Slider::Slider(const Point &iPos, const Size &iSize, Int sType, Int *var, Int rangeStart, Int rangeEnd) : Widget(iPos, iSize) { type = classID; subtype = sType; startValue = rangeStart; endValue = rangeEnd; dummyVariable = 0; previousValue = 0; gripSize = 9; if (var == NIL) variable = &dummyVariable; else variable = var; if (GetWidth() == 0 && subtype == OR_HORZ) SetWidth(100); if (GetHeight() == 0 && subtype == OR_VERT) SetHeight(100); if (subtype == OR_HORZ) SetHeight(18); else SetWidth(18); onValueChange.SetParentObject(this); onValueChange.Connect(&onAction); clickHotspot = new Hotspot(subtype == OR_HORZ ? Point(4, 1) : Point(1, 4), GetSize() - (subtype == OR_HORZ ? Size(8, 2) : Size(2, 8))); dragHotspot = new Hotspot(Point(), Size()); dragging = False; clickHotspot->onLeftButtonClick.Connect(&Slider::OnMouseClick, this); dragHotspot->onMouseDragStart.Connect(&Slider::OnMouseDragStart, this); dragHotspot->onMouseDrag.Connect(&Slider::OnMouseDrag, this); dragHotspot->onMouseDragEnd.Connect(&Slider::OnMouseDragEnd, this); Add(clickHotspot); Add(dragHotspot); onChangeSize.Connect(&Slider::UpdateHotspotPositions, this); SetValue(*variable); UpdateHotspotPositions(); } S::GUI::Slider::~Slider() { DeleteObject(clickHotspot); DeleteObject(dragHotspot); } S::Int S::GUI::Slider::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Int realGripSize = Math::Round(gripSize * surface->GetSurfaceDPI() / 96.0); Rect sliderRect; switch (message) { case SP_PAINT: surface->StartPaint(Rect(realPos, realSize)); surface->Box(Rect(realPos, realSize), GetBackgroundColor(), Rect::Filled); if (subtype == OR_HORZ) surface->Bar(realPos + Point((realGripSize - 1) / 2, (realSize.cy - 2) / 2), realPos + Point(realSize.cx - (realGripSize - 1) / 2, (realSize.cy - 2) / 2), OR_HORZ); else surface->Bar(realPos + Point((realSize.cy - 2) / 2, (realGripSize - 1) / 2), realPos + Point((realSize.cy - 2) / 2, realSize.cy - (realGripSize - 1) / 2), OR_VERT); if (subtype == OR_HORZ) sliderRect = Rect(realPos + Point((Int) (((Float) (realSize.cx - realGripSize)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue))), 0), Size(gripSize - 1, 16) * surface->GetSurfaceDPI() / 96.0 + Size(1, 1)); else sliderRect = Rect(realPos + Point(0, (realSize.cy - realGripSize - 1) - (Int) (((Float) (realSize.cy - realGripSize - 1)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue)))), Size(16, gripSize - 1) * surface->GetSurfaceDPI() / 96.0 + Size(2, 2)); if (!dragging) surface->Box(sliderRect, Setup::BackgroundColor, Rect::Filled); else surface->Box(sliderRect, Setup::LightGrayColor, Rect::Filled); surface->Frame(sliderRect, FRAME_UP); surface->EndPaint(); break; } return Success(); } S::Int S::GUI::Slider::SetRange(Int rangeStart, Int rangeEnd) { if (startValue == rangeStart && endValue == rangeEnd) return Success(); startValue = rangeStart; endValue = rangeEnd; *variable = Math::Min(Math::Max(*variable, startValue), endValue); Paint(SP_PAINT); UpdateHotspotPositions(); return Success(); } S::Void S::GUI::Slider::SetValue(Int newValue) { Int previousVariable = *variable; *variable = Math::Min(Math::Max(newValue, startValue), endValue); if (*variable != previousValue) { if (!dragging) { Point prevPosition = dragHotspot->GetPosition(); UpdateHotspotPositions(); if (dragHotspot->GetPosition() != prevPosition) Paint(SP_PAINT); } previousValue = *variable; if (*variable != previousVariable) onValueChange.Emit(*variable); } } S::Int S::GUI::Slider::SetGripSize(Int newGripSize) { gripSize = newGripSize; Paint(SP_PAINT); UpdateHotspotPositions(); return Success(); } S::Void S::GUI::Slider::OnMouseClick(const Point &mousePos) { Int value = 0; Point realPos = GetRealPosition(); Size realSize = GetRealSize(); if (subtype == OR_HORZ) value = Math::Round(((Float) (endValue - startValue)) / (((Float) realSize.cx - gripSize) / ((Float) (mousePos.x - (realPos.x + gripSize / 2))))); else value = Math::Round(((Float) (endValue - startValue)) / (((Float) realSize.cy - gripSize) / ((Float) (mousePos.y - (realPos.y + gripSize / 2))))); if (!dragging) { if (subtype == OR_HORZ) SetValue(startValue + value); else SetValue(endValue - value); } } S::Void S::GUI::Slider::OnMouseDragStart(const Point &mousePos) { Point realPos = GetRealPosition(); Size realSize = GetRealSize(); if (subtype == OR_HORZ) mouseBias = (realPos.x + (Int) (((Float) (realSize.cx - gripSize)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue))) + gripSize / 2) - mousePos.x; else mouseBias = (realPos.y + (realSize.cy - gripSize) - (Int) (((Float) (realSize.cy - gripSize)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue))) + gripSize / 2) - mousePos.y; dragging = True; } S::Void S::GUI::Slider::OnMouseDrag(const Point &mousePos) { Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Int value = 0; if (subtype == OR_HORZ) value = Math::Round(((Float) (endValue - startValue)) / (((Float) realSize.cx - gripSize) / ((Float) (mousePos.x + mouseBias - (realPos.x + gripSize / 2))))); else value = Math::Round(((Float) (endValue - startValue)) / (((Float) realSize.cy - gripSize) / ((Float) (mousePos.y + mouseBias - (realPos.y + gripSize / 2))))); dragging = False; if (subtype == OR_HORZ) SetValue(startValue + value); else SetValue(endValue - value); dragging = True; } S::Void S::GUI::Slider::OnMouseDragEnd(const Point &mousePos) { OnMouseDrag(mousePos); dragging = False; Paint(SP_PAINT); } S::Void S::GUI::Slider::UpdateHotspotPositions() { clickHotspot->SetSize(GetSize() - (subtype == OR_HORZ ? Size(8, 2) : Size(2, 8))); dragHotspot->SetMetrics(subtype == OR_HORZ ? Point((Int) (((Float) (GetWidth() - gripSize)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue))), 0) : Point(0, (GetHeight() - gripSize) - (Int) (((Float) (GetHeight() - gripSize)) / ((Float) (endValue - startValue)) * ((Float) (*variable - startValue)))), subtype == OR_HORZ ? Size(gripSize - 1, 16) : Size(16, gripSize - 1)); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/statusbar.cpp000077500000000000000000000064241516402577000254550ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #ifdef __APPLE__ # include #endif const S::Short S::GUI::Statusbar::classID = S::Object::RequestClassID(); S::GUI::Statusbar::Statusbar(const String &status) : Widget(Point(), Size(0, 16)) { type = classID; text = status; orientation = OR_BOTTOM; } S::GUI::Statusbar::~Statusbar() { } S::Int S::GUI::Statusbar::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->Box(frame, Setup::BackgroundColor, Rect::Filled); surface->SetText(text, frame + Point(4 * surface->GetSurfaceDPI() / 96.0, Math::Ceil(Float(frame.GetHeight() - font.GetScaledTextSizeY()) / 2) - 1) - Size(8, 2) * surface->GetSurfaceDPI() / 96.0, font); } break; }; Int occupied_right = 5; Int occupied_left = 5; #ifdef __APPLE__ /* Check if macOS version is lower than 10.7 (Darwin 11.0) and * occupy ten pixels for the handle at the right in that case. */ Int resizeGripSize = (Backends::BackendCocoa::IsOSXVersionAtLeast(10, 7, 0) ? 0 : 10); occupied_right += resizeGripSize; if (resizeGripSize > 0) { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->Line(Point(frame.right - 2, frame.bottom - 1), Point(frame.right, frame.bottom - 3), Color(116, 116, 116)); surface->Line(Point(frame.right - 3, frame.bottom - 1), Point(frame.right, frame.bottom - 4), Color(184, 184, 184)); surface->Line(Point(frame.right - 6, frame.bottom - 1), Point(frame.right, frame.bottom - 7), Color(116, 116, 116)); surface->Line(Point(frame.right - 7, frame.bottom - 1), Point(frame.right, frame.bottom - 8), Color(184, 184, 184)); surface->Line(Point(frame.right - 10, frame.bottom - 1), Point(frame.right, frame.bottom - 11), Color(116, 116, 116)); surface->Line(Point(frame.right - 11, frame.bottom - 1), Point(frame.right, frame.bottom - 12), Color(184, 184, 184)); } #endif for (Int i = 0; i < GetNOfObjects(); i++) { Widget *object = GetNthObject(i); if (object->GetOrientation() == OR_UPPERRIGHT) { object->SetPosition(Point(occupied_right + object->GetWidth(), (GetHeight() - object->GetHeight()) / 2)); occupied_right += object->GetWidth() + 5; } else if (object->GetOrientation() == OR_UPPERLEFT) { object->SetPosition(Point(occupied_left, (GetHeight() - object->GetHeight()) / 2)); occupied_left += object->GetWidth() + 5; } } return Widget::Paint(message); } S::Int S::GUI::Statusbar::SetText(const String &newStatus) { if (text == newStatus) return Success(); text = newStatus; Paint(SP_PAINT); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/tabwidget.cpp000077500000000000000000000161061516402577000254150ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::GUI::TabWidget::classID = S::Object::RequestClassID(); S::GUI::TabWidget::TabWidget(const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { type = classID; if (GetWidth() == 0) SetWidth(120); if (GetHeight() == 0) SetHeight(100); selectedTab = NIL; onSelectTab.SetParentObject(this); onChangeSize.Connect(&TabWidget::OnChangeSize, this); } S::GUI::TabWidget::~TabWidget() { } S::Int S::GUI::TabWidget::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Int offset = 19 * surface->GetSurfaceDPI() / 96; Long lightColor = Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255)); Long darkColor = Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0)); surface->Box(frame, Setup::BackgroundColor, Rect::Filled); surface->Frame(frame + Point(0, offset) - Size(0, offset), FRAME_UP); frame.right = frame.left; frame.bottom = frame.top + offset; for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); Widget *prev = (i > 0) ? GetNthObject(i - 1) : NIL; const Bitmap &bitmap = bitmaps.Get(widget->GetHandle()); Size sSize = bitmap == NIL ? Size() : Size(bitmap.GetSize().cx / (bitmap.GetSize().cy / 15.0) , 15) * surface->GetSurfaceDPI() / 96; frame.left = frame.right + 1; frame.right = frame.left + widget->GetScaledTextWidth() + sSize.cx + 6 + Int(widget->GetText() != NIL ? 6 : 0); if (widget->IsVisible()) { frame.left--; frame.right++; } else { frame.top++; } if (prev != NIL && prev->IsVisible()) frame.left++; surface->Frame(frame + Size(1, 1), FRAME_UP); if (IsRightToLeft()) { frame.left++; frame.right++; } if (prev != NIL && prev->IsVisible()) { surface->Line(Point(frame.left, frame.top + 1), Point(frame.left, frame.bottom), Setup::BackgroundColor); frame.left--; if (IsRightToLeft()) surface->SetPixel(Point(frame.left + 1, frame.top), lightColor); } else { surface->SetPixel(Point(frame.left, frame.top), Setup::BackgroundColor); } surface->SetPixel(Point(frame.right, frame.top), Setup::BackgroundColor); if (IsRightToLeft()) { frame.left--; frame.right--; } if (widget->IsVisible()) frame.bottom--; if (bitmap != NIL) { surface->BlitFromBitmap(bitmap, Rect(Point(0, 0), bitmap.GetSize()), Rect(Point(frame.left + 3 + (widget->IsVisible() ? 1 : 0), frame.top + 2), sSize)); } surface->SetText(widget->GetText(), Rect(Point(frame.left + sSize.cx + 6 + (widget->IsVisible() ? 1 : 0), frame.top + Math::Ceil(Float(frame.GetHeight() - widget->GetFont().GetScaledTextSizeY()) / 2) - 1), Size(widget->GetScaledTextWidth() + sSize.cx, offset - 2)), widget->GetFont()); if (widget->IsVisible()) { frame.bottom++; surface->Line(Point(frame.left + 1, frame.bottom), Point(frame.right + (IsRightToLeft() ? 1 : 0), frame.bottom), Setup::BackgroundColor); surface->SetPixel(Point(frame.left + (IsRightToLeft() ? 1 : 0), frame.bottom), (IsRightToLeft() ? darkColor : lightColor)); if (IsRightToLeft()) surface->SetPixel(Point(frame.right + 1, frame.bottom), lightColor); frame.right--; } else { if (prev != NIL && prev->IsVisible()) frame.left++; surface->Line(Point(frame.left, frame.bottom), Point(frame.right + (IsRightToLeft() ? 2 : 1), frame.bottom), lightColor); if (prev != NIL && prev->IsVisible()) frame.left--; frame.top--; } } } break; } return Widget::Paint(message); } S::Int S::GUI::TabWidget::Process(Int message, Int wParam, Int lParam) { if (!IsRegistered()) return Error(); if (!IsActive() || !IsVisible()) return Success(); switch (message) { case SM_LBUTTONDOWN: { Window *window = container->GetContainerWindow(); Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); Int offset = 19 * surface->GetSurfaceDPI() / 96; Rect frame = Rect(Point(0, realPos.y + 1), Size(realPos.x, offset - 1)); for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); const Bitmap &bitmap = bitmaps.Get(widget->GetHandle()); Size sSize = bitmap == NIL ? Size() : Size(bitmap.GetSize().cx / (bitmap.GetSize().cy / 15.0) , 15) * surface->GetSurfaceDPI() / 96; frame.left = frame.right + 1; frame.right = frame.left + widget->GetScaledTextWidth() + sSize.cx + 6 + Int(widget->GetText() != NIL ? 6 : 0); if (!widget->IsVisible() && window->IsMouseOn(frame)) { SelectTab(widget); break; } } } break; } return Widget::Process(message, wParam, lParam); } S::Int S::GUI::TabWidget::SelectTab(const Widget *tabWidget) { for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); if (widget != tabWidget) continue; Surface *surface = GetDrawSurface(); surface->StartPaint(GetVisibleArea()); for (Int j = 0; j < GetNOfObjects(); j++) { if (j == i) continue; GetNthObject(j)->Hide(); } widget->Show(); Paint(SP_PAINT); surface->EndPaint(); selectedTab = widget; onSelectTab.Emit(widget); return Success(); } return Error(); } S::Void S::GUI::TabWidget::OnChangeSize(const Size &nSize) { for (Int i = 0; i < GetNOfObjects(); i++) GetNthObject(i)->SetSize(nSize - Size(3, 22)); } S::Int S::GUI::TabWidget::Add(Widget *widget) { return Add(widget, NIL); } S::Int S::GUI::TabWidget::Add(Widget *widget, const Bitmap &bitmap) { if (widget == NIL) return Error(); if (!widget->IsRegistered()) { widget->Hide(); if (Widget::Add(widget) == Success()) { bitmaps.Add(bitmap, widget->GetHandle()); widget->SetMetrics(Point(2, 21), GetSize() - Size(3, 22)); if (GetNOfObjects() == 1) SelectTab(widget); return Success(); } } return Error(); } S::Int S::GUI::TabWidget::Remove(Widget *widget) { if (widget == NIL) return Error(); Bool wasVisible = widget->IsVisible(); if (Widget::Remove(widget) == Success()) { bitmaps.Remove(widget->GetHandle()); if (wasVisible) { if (GetNOfObjects() > 0) SelectTab(GetNthObject(0)); else selectedTab = NIL; } return Success(); } return Error(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/text.cpp000077500000000000000000000064271516402577000244340ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2015 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::GUI::Text::classID = S::Object::RequestClassID(); S::GUI::Text::Text(const String &iText, const Point &iPos, const Size &iAlign) : Widget(iPos, Size()) { type = classID; text = iText; align = iAlign; ComputeTextSize(); SetSize(scaledTextSize * 96.0 / Surface().GetSurfaceDPI() + Size(0, 2)); } S::GUI::Text::~Text() { } S::Int S::GUI::Text::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: if (text != NIL) { Font nFont = font; if (!IsActive()) nFont.SetColor(Setup::InactiveTextColor); Rect rect = Rect(GetRealPosition(), GetRealSize()); Surface *surface = GetDrawSurface(); Size alignToUse = Size(align.cx, (font.GetSize() == Font::DefaultSize && align.cy == 0) ? 13 : align.cy); Point alignment = Point(alignToUse.cx == 0 ? 0 : Math::Ceil(Float(Float(alignToUse.cx) * surface->GetSurfaceDPI() / 96.0 - font.GetScaledTextSizeX(text)) / 2) - 1, alignToUse.cy == 0 ? 0 : Math::Ceil(Float(Float(alignToUse.cy) * surface->GetSurfaceDPI() / 96.0 - font.GetScaledTextSizeY()) / 2) - 1); surface->Box(rect + alignment, GetBackgroundColor(), Rect::Filled); surface->SetText(text, Rect::OverlapRect(Rect(rect.GetPosition() + alignment, Size(scaledTextSize.cx, Math::Round(scaledTextSize.cy * 1.2))), GetVisibleArea() + alignment), nFont); } break; } return Success(); } S::Int S::GUI::Text::SetText(const String &nText) { if (text == nText) return Success(); Surface *surface = GetDrawSurface(); Bool registered = IsRegistered(); Bool visible = IsVisible(); if (registered && visible) { Rect oldRect = Rect(GetRealPosition(), GetRealSize()); Rect newRect = Rect(oldRect.GetPosition(), Size(font.GetScaledTextSizeX(nText), font.GetScaledTextSizeY(nText))); surface->StartPaint(Rect::EncloseRect(oldRect, newRect)); } Widget::SetText(nText); SetSize(scaledTextSize * 96.0 / Surface().GetSurfaceDPI() + Size(0, 2)); Paint(SP_PAINT); if (registered && visible) surface->EndPaint(); return Success(); } S::Int S::GUI::Text::SetFont(const Font &nFont) { if (font == nFont) return Success(); Surface *surface = GetDrawSurface(); Bool registered = IsRegistered(); Bool visible = IsVisible(); if (registered && visible) { Rect oldRect = Rect(GetRealPosition(), GetRealSize()); Rect newRect = Rect(oldRect.GetPosition(), Size(nFont.GetScaledTextSizeX(text), nFont.GetScaledTextSizeY(text))); surface->StartPaint(Rect::EncloseRect(oldRect, newRect)); } Widget::SetFont(nFont); SetSize(scaledTextSize * 96.0 / Surface().GetSurfaceDPI() + Size(0, 2)); Paint(SP_PAINT); if (registered && visible) surface->EndPaint(); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/basic/titlebar.cpp000077500000000000000000000311251516402577000252470ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #ifdef __WIN32__ # include #endif const S::Short S::GUI::Titlebar::classID = S::Object::RequestClassID(); S::GUI::Titlebar::Titlebar(Int buttons) : Widget(Point(), Size(0, 19)) { type = classID; paintActive = True; flags = buttons; orientation = OR_TOP; subtype = WO_NOSEPARATOR; font.SetWeight(Font::Bold); #ifdef __WIN32__ static Bool flatStyle = Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2); if (flatStyle) { minHotspot = new Hotspot(Point(39, 4), Size(11, 11)); maxHotspot = new Hotspot(Point(28, 4), Size(11, 11)); closeHotspot = new Hotspot(Point(17, 4), Size(11, 11)); } else { minHotspot = new HotspotSimpleButton(Point(37, 5), Size(11, 11)); maxHotspot = new HotspotSimpleButton(Point(27, 5), Size(11, 11)); closeHotspot = new HotspotSimpleButton(Point(17, 5), Size(11, 11)); } minHotspot->SetOrientation(OR_UPPERRIGHT); maxHotspot->SetOrientation(OR_UPPERRIGHT); closeHotspot->SetOrientation(OR_UPPERRIGHT); minHotspot->hitTest.Connect(&Titlebar::ButtonHitTest, this); maxHotspot->hitTest.Connect(&Titlebar::ButtonHitTest, this); closeHotspot->hitTest.Connect(&Titlebar::ButtonHitTest, this); minHotspot->onLeftButtonClick.Connect(&Titlebar::OnMinButtonClick, this); maxHotspot->onLeftButtonClick.Connect(&Titlebar::OnMaxButtonClick, this); closeHotspot->onLeftButtonClick.Connect(&Titlebar::OnCloseButtonClick, this); if (Binary::IsFlagSet(flags, TB_MINBUTTON)) Add(minHotspot); if (Binary::IsFlagSet(flags, TB_MAXBUTTON)) Add(maxHotspot); if (Binary::IsFlagSet(flags, TB_CLOSEBUTTON)) Add(closeHotspot); dragHotspot = new Hotspot(Point(0, 0), Size(4096, 19)); dragHotspot->onMouseDragStart.Connect(&Titlebar::OnMouseDragStart, this); dragHotspot->hitTest.Connect(&Titlebar::DragHitTest, this); dragHotspot->onMouseDrag.Connect(&Titlebar::OnMouseDrag, this); if (Binary::IsFlagSet(flags, TB_MAXBUTTON)) dragHotspot->onLeftButtonDoubleClick.Connect(&Titlebar::OnMaxButtonClick, this); Add(dragHotspot); closeShortcut = new Shortcut(0, Input::Keyboard::KeyEscape); closeShortcut->onKeyDown.Connect(&Titlebar::OnCloseButtonClick, this); if ( Binary::IsFlagSet(flags, TB_CLOSEBUTTON) && !Binary::IsFlagSet(flags, TB_MINBUTTON) && !Binary::IsFlagSet(flags, TB_MAXBUTTON)) Add(closeShortcut); #else SetHeight(0); #endif } S::GUI::Titlebar::~Titlebar() { #ifdef __WIN32__ DeleteObject(minHotspot); DeleteObject(maxHotspot); DeleteObject(closeHotspot); DeleteObject(dragHotspot); DeleteObject(closeShortcut); #endif } S::Int S::GUI::Titlebar::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); #ifdef __WIN32__ Surface *surface = GetDrawSurface(); Window *window = container->GetContainerWindow(); static Bool flatStyle = Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2); Rect titleFrame = Rect(GetRealPosition(), GetRealSize()); Rect buttonRect = Rect(Point(titleFrame.right - Math::Round(4 * surface->GetSurfaceDPI() / 96.0) - Math::Round((5 + 10 * (Binary::IsFlagSet(flags, TB_MINBUTTON) || Binary::IsFlagSet(flags, TB_MAXBUTTON) ? 3 : 1)) * surface->GetSurfaceDPI() / 96.0), titleFrame.top + (flatStyle ? 2 : 3)), Size(Math::Round((5 + 10 * (Binary::IsFlagSet(flags, TB_MINBUTTON) || Binary::IsFlagSet(flags, TB_MAXBUTTON) ? 3 : 1)) * surface->GetSurfaceDPI() / 96.0), titleFrame.GetHeight() - 5)); Rect button; Point start; Point end; text = window->GetText(); if (flatStyle && (Binary::IsFlagSet(flags, TB_MINBUTTON) || Binary::IsFlagSet(flags, TB_MAXBUTTON))) buttonRect.left -= 2; Color titlebarStartColor = paintActive ? Setup::TitlebarStartColor : Setup::InactiveTitlebarStartColor; Color titlebarEndColor = paintActive ? Setup::TitlebarEndColor : Setup::InactiveTitlebarEndColor; Color titlebarTextColor = paintActive ? Setup::TitlebarTextColor : Setup::InactiveTitlebarTextColor; Color buttonColor; switch (message) { case SP_PAINT: surface->StartPaint(titleFrame - Point(1, 1) + Size(2, 1)); if (flatStyle) { surface->Gradient(titleFrame - Point(1, 1) + Size(2, 1), titlebarStartColor, titlebarEndColor, OR_HORZ); } if (window->GetIcon() != NIL) titleFrame.left += titleFrame.GetHeight() - 1; if (!flatStyle) { surface->Frame(titleFrame, FRAME_UP); surface->Gradient(titleFrame + Point(1, 1) - Size(2, 2), titlebarStartColor, titlebarEndColor, OR_HORZ); } font.SetColor(titlebarTextColor); surface->SetText(text, titleFrame + Point(4, Math::Ceil(Float(titleFrame.GetHeight() - font.GetScaledTextSizeY()) / 2) - 1 - (flatStyle ? 1 : 0)) - Size(9, 6), font); if (window->GetIcon() != NIL) surface->BlitFromBitmap(window->GetIcon(), Rect(Point(0, 0), window->GetIcon().GetSize()), Rect(Point(titleFrame.left - 16 * surface->GetSurfaceDPI() / 96.0 - (flatStyle ? 0 : 2), titleFrame.top + (flatStyle ? 1 : 2)), Size(16, 16) * surface->GetSurfaceDPI() / 96.0)); if (!flatStyle) { surface->Box(buttonRect, Setup::BackgroundColor, Rect::Filled); surface->Frame(buttonRect, FRAME_DOWN); } button = Rect(Point(buttonRect.left + Math::Round(4 * surface->GetSurfaceDPI() / 96.0), buttonRect.bottom - Math::Round(5 * surface->GetSurfaceDPI() / 96.0)), Size(Math::Round(7 * surface->GetSurfaceDPI() / 96.0), 2)); if (Binary::IsFlagSet(flags, TB_MINBUTTON) || Binary::IsFlagSet(flags, TB_MAXBUTTON)) { if (Binary::IsFlagSet(flags, TB_MINBUTTON)) buttonColor = Setup::TextColor; else buttonColor = Setup::InactiveTextColor; surface->Box(button, buttonColor, Rect::Filled); button = button + Point(button.GetWidth() + Math::Round(2 * surface->GetSurfaceDPI() / 96.0) + (flatStyle ? 2 : 1), 0); } button.top = buttonRect.top + Math::Round(5 * surface->GetSurfaceDPI() / 96.0); if (Binary::IsFlagSet(flags, TB_MINBUTTON) || Binary::IsFlagSet(flags, TB_MAXBUTTON)) { if (Binary::IsFlagSet(flags, TB_MAXBUTTON)) buttonColor = Setup::TextColor; else buttonColor = Setup::InactiveTextColor; if (window->IsMaximized()) { surface->Box(button + Point(1, -1) - Size(1, 1), buttonColor, Rect::Outlined); surface->Box(button + Point(1, -2) - Size(1, 0), buttonColor, Rect::Outlined); surface->Box(button + Point(-1, 2) - Size(1, 1), flatStyle ? titlebarEndColor : Setup::BackgroundColor, Rect::Filled); surface->Box(button + Point(-1, 2) - Size(1, 1), buttonColor, Rect::Outlined); surface->Box(button + Point(-1, 1) - Size(1, 0), buttonColor, Rect::Outlined); } else { surface->Box(button, buttonColor, Rect::Outlined); surface->Box(button - Point(0, 1) + Size(0, 1), buttonColor, Rect::Outlined); } button = button + Point(button.GetWidth() + Math::Round(2 * surface->GetSurfaceDPI() / 96.0) + (flatStyle ? 2 : 1), 0); } start = Point(button.left + (IsRightToLeft() ? 1 : 0), button.top - 1); end = Point(button.right + (IsRightToLeft() ? 1 : 0), button.bottom); if (Binary::IsFlagSet(flags, TB_CLOSEBUTTON)) buttonColor = Setup::TextColor; else buttonColor = Setup::InactiveTextColor; surface->Line(start, end, buttonColor); surface->Line(start + Point(1, 0), end - Point(0, 1), buttonColor); surface->Line(start + Point(0, 1), end - Point(1, 0), buttonColor); start = Point(button.left + (IsRightToLeft() ? 1 : 0), button.bottom - 1); end = Point(button.right + (IsRightToLeft() ? 1 : 0), button.top - 2); surface->Line(start, end, buttonColor); surface->Line(start + Point(1, 0), end + Point(0, 1), buttonColor); surface->Line(start - Point(0, 1), end - Point(1, 0), buttonColor); surface->EndPaint(); break; } #endif return Success(); } S::Int S::GUI::Titlebar::Process(Int message, Int wParam, Int lParam) { if (!IsRegistered()) return Error(); if (!IsActive() || !IsVisible()) return Success(); #ifdef __WIN32__ Window *window = container->GetContainerWindow(); #endif Bool prevPaintActive = paintActive; switch (message) { case SM_GETFOCUS: case SM_LOSEFOCUS: case SM_WINDOWTITLECHANGED: #ifdef __WIN32__ if (GetActiveWindow() == (HWND) window->GetSystemWindow() && (!paintActive || message == SM_WINDOWTITLECHANGED)) { paintActive = True; } else if (GetActiveWindow() != (HWND) window->GetSystemWindow()) { paintActive = False; Widget *remoteParent = Window::GetWindow(GetActiveWindow()); if (remoteParent != NIL) { if (remoteParent->GetObjectType() == ToolWindow::classID) { do { remoteParent = remoteParent->GetContainer(); if (remoteParent == window) { paintActive = True; break; } } while (remoteParent != NIL); } } } #endif if (message == SM_WINDOWTITLECHANGED || paintActive != prevPaintActive) Paint(SP_PAINT); break; } return Widget::Process(message, wParam, lParam); } S::Void S::GUI::Titlebar::OnMouseDragStart(const Point &mousePos) { startMousePos = mousePos; } S::Void S::GUI::Titlebar::OnMouseDrag(const Point &mousePos) { Window *window = container->GetContainerWindow(); if (window->IsMaximized() && mousePos != startMousePos) { Rect nonMaxRect = window->GetRestoredWindowRect(); Rect workArea = System::Screen::GetActiveScreenWorkArea(); window->Restore(); window->SetPosition(Point(workArea.left + Math::Max(0, Math::Min(mousePos.x - nonMaxRect.GetWidth() / 2, workArea.GetWidth() - nonMaxRect.GetWidth())), workArea.top + mousePos.y - startMousePos.y)); startMousePos.x -= window->GetX(); } if (!window->IsMaximized()) window->SetPosition(window->GetPosition() - (Point((IsRightToLeft() ? window->GetWidth() - startMousePos.x : startMousePos.x), startMousePos.y) - Point((IsRightToLeft() ? window->GetWidth() - mousePos.x : mousePos.x), mousePos.y))); } S::Void S::GUI::Titlebar::OnMinButtonClick() { Window *window = container->GetContainerWindow(); window->Minimize(); } S::Void S::GUI::Titlebar::OnMaxButtonClick() { Window *window = container->GetContainerWindow(); if (window->IsMaximized()) window->Restore(); else window->Maximize(); } S::Void S::GUI::Titlebar::OnCloseButtonClick() { Window *window = container->GetContainerWindow(); window->Close(); } S::Bool S::GUI::Titlebar::ButtonHitTest(const Point &mousePos) { Surface *surface = GetDrawSurface(); return (mousePos.x >= 1 && mousePos.y >= 1 && mousePos.x <= 9 * surface->GetSurfaceDPI() / 96.0 && mousePos.y <= 9 * surface->GetSurfaceDPI() / 96.0); } S::Bool S::GUI::Titlebar::DragHitTest(const Point &mousePos) { Surface *surface = GetDrawSurface(); Window *window = container->GetContainerWindow(); #ifdef __WIN32__ static Bool flatStyle = Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2); #else static Bool flatStyle = False; #endif Rect titleFrame = Rect(Point(0,0), GetRealSize()); Rect buttonRect = Rect(Point(titleFrame.right - Math::Round(4 * surface->GetSurfaceDPI() / 96.0) - Math::Round((5 + 10 * (Binary::IsFlagSet(flags, TB_MINBUTTON) || Binary::IsFlagSet(flags, TB_MAXBUTTON) ? 3 : 1)) * surface->GetSurfaceDPI() / 96.0) + (flatStyle ? 2 : 0), titleFrame.top + (flatStyle ? 4 : 3)), Size(Math::Round((5 + 10 * (Binary::IsFlagSet(flags, TB_MINBUTTON) || Binary::IsFlagSet(flags, TB_MAXBUTTON) ? 3 : 1)) * surface->GetSurfaceDPI() / 96.0) - (flatStyle ? 5 : 1), titleFrame.GetHeight() - (flatStyle ? 9 : 6))); if (!flatStyle && window->GetIcon() != NIL) titleFrame.left += titleFrame.GetHeight() - 1; if (flatStyle && (Binary::IsFlagSet(flags, TB_MINBUTTON) || Binary::IsFlagSet(flags, TB_MAXBUTTON))) buttonRect.left -= 2; return ((mousePos.x >= titleFrame.left && mousePos.y >= titleFrame.top && mousePos.x <= titleFrame.right && mousePos.y <= titleFrame.bottom) && !(mousePos.x >= buttonRect.left && mousePos.y >= buttonRect.top && mousePos.x <= buttonRect.right && mousePos.y <= buttonRect.bottom)); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/hotspot/000077500000000000000000000000001516402577000233475ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/hotspot/Makefile000066400000000000000000000004711516402577000250110ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. # Enter object files here: OBJECTS = hotspot.o simplebutton.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/hotspot/hotspot.cpp000077500000000000000000000026001516402577000255540ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include const S::Short S::GUI::Hotspot::classID = S::Object::RequestClassID(); S::GUI::Hotspot::Hotspot(const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { type = classID; } S::GUI::Hotspot::~Hotspot() { } S::Int S::GUI::Hotspot::Show() { if (visible) return Success(); visible = True; Process(SM_MOUSEMOVE, 0, 0); onShow.Emit(); return Success(); } S::Int S::GUI::Hotspot::Hide() { if (!visible) return Success(); visible = False; mouseOver = False; leftButtonDown = False; rightButtonDown = False; onHide.Emit(); return Success(); } S::Int S::GUI::Hotspot::Activate() { active = True; Paint(SP_MOUSEOUT); Process(SM_MOUSEMOVE, 0, 0); onActivate.Emit(); return Success(); } S::Int S::GUI::Hotspot::Deactivate() { active = False; mouseOver = False; leftButtonDown = False; rightButtonDown = False; mouseDragging = False; onDeactivate.Emit(); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/hotspot/simplebutton.cpp000077500000000000000000000024651516402577000266120ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2011 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include const S::Short S::GUI::HotspotSimpleButton::classID = S::Object::RequestClassID(); S::GUI::HotspotSimpleButton::HotspotSimpleButton(const Point &iPos, const Size &iSize) : Hotspot(iPos, iSize) { type = classID; } S::GUI::HotspotSimpleButton::~HotspotSimpleButton() { } S::Int S::GUI::HotspotSimpleButton::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); switch (message) { case SP_MOUSEIN: case SP_MOUSEUP: surface->Frame(frame, FRAME_UP); break; case SP_MOUSEDOWN: surface->Frame(frame, FRAME_DOWN); break; case SP_MOUSEOUT: surface->Box(frame, GetBackgroundColor(), Rect::Outlined); break; } return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/layer.cpp000077500000000000000000000027011516402577000234720ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::Layer::classID = S::Object::RequestClassID(); S::GUI::Layer::Layer(const String &name) : Widget(Point(0, 0), Size(32768, 32768)) { type = classID; text = name; orientation = OR_CENTER; ComputeTextSize(); } S::GUI::Layer::~Layer() { } S::Int S::GUI::Layer::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: if (IsBackgroundColorSet()) { Surface *surface = GetDrawSurface(); surface->Box(Rect(GetRealPosition(), GetRealSize()), GetBackgroundColor(), Rect::Filled); } break; } return Widget::Paint(message); } S::Int S::GUI::Layer::SetMetrics(const Point &iPos, const Size &iSize) { if (orientation == OR_CENTER) orientation = OR_FREE; return Widget::SetMetrics(iPos, iSize); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/000077500000000000000000000000001516402577000230015ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/Makefile000066400000000000000000000006701516402577000244440ustar00rootroot00000000000000########## smooth directory $(MAKE)file ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options all: $(call makein,generic) $(call makein,image) $(call makein,list) $(call makein,menu) $(call makein,tree) clean: $(call cleanin,generic) $(call cleanin,image) $(call cleanin,list) $(call cleanin,menu) $(call cleanin,tree) smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/generic/000077500000000000000000000000001516402577000244155ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/generic/Makefile000066400000000000000000000004671516402577000260640ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. # Enter object files here: OBJECTS = container.o entry.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/generic/container.cpp000066400000000000000000000051451516402577000271100ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include const S::Short S::GUI::Container::classID = S::Object::RequestClassID(); S::GUI::Container::Container() : Widget(Point(), Size()) { type = classID; onChangeEntryOrder.SetParentObject(this); } S::GUI::Container::~Container() { onChangeEntryOrder.DisconnectAll(); RemoveAllEntries(); } S::Int S::GUI::Container::EnableLocking(Bool enable) { if (enable) { createdEntry.EnableLocking(); elementOrder.EnableLocking(); } else { createdEntry.DisableLocking(); elementOrder.DisableLocking(); } return Widget::EnableLocking(enable); } S::Int S::GUI::Container::Add(Widget *widget) { if (widget == NIL) return Error(); if (!widget->IsRegistered()) { if (Widget::Add(widget) == Success() && widget->GetObjectType() == Entry::classID) { elementOrder.Add((Entry *) widget, widget->GetHandle()); createdEntry.Add(False, widget->GetHandle()); Paint(SP_UPDATE); Process(SM_MOUSEMOVE, 0, 0); onChangeEntryOrder.Emit(); return Success(); } } return Error(); } S::Int S::GUI::Container::Remove(Widget *widget) { if (widget == NIL) return Error(); if (Widget::Remove(widget) == Success() && widget->GetObjectType() == Entry::classID) { Int entryHandle = widget->GetHandle(); if (createdEntry.Get(entryHandle)) DeleteObject(widget); elementOrder.Remove(entryHandle); createdEntry.Remove(entryHandle); Paint(SP_UPDATE); Process(SM_MOUSEMOVE, 0, 0); onChangeEntryOrder.Emit(); return Success(); } return Error(); } S::Int S::GUI::Container::RemoveAllEntries() { Surface *surface = GetDrawSurface(); Bool visible = IsVisible(); if (visible) { Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->StartPaint(frame); Hide(); } while (Length() > 0) Remove(GetNthEntry(Length() - 1)); if (visible) { Show(); surface->EndPaint(); } return Success(); } S::Int S::GUI::Container::MoveEntry(Int n, Int m) { if (n == m) return Success(); if (n >= Length() || m >= Length()) return Error(); if (n < 0 || m < 0 ) return Error(); elementOrder.MoveNth(n, m); onChangeEntryOrder.Emit(); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/generic/entry.cpp000066400000000000000000000012351516402577000262630ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include const S::Short S::GUI::Entry::classID = S::Object::RequestClassID(); S::GUI::Entry::Entry() : Widget(Point(), Size()) { type = classID; } S::GUI::Entry::~Entry() { } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/image/000077500000000000000000000000001516402577000240635ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/image/Makefile000066400000000000000000000004731516402577000255270ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. # Enter object files here: OBJECTS = imagebox.o imageentry.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/image/imagebox.cpp000077500000000000000000000117361516402577000263750ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2015 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::ImageBox::classID = S::Object::RequestClassID(); S::GUI::ImageBox::ImageBox(const Point &iPos, const Size &iSize) { type = classID; scrollbar = NIL; scrollbarPos = 0; SetBackgroundColor(Setup::ClientColor); SetMetrics(iPos, iSize); if (GetWidth() == 0) SetWidth(120); if (GetHeight() == 0) SetHeight(80); onChangeSize.Connect(&ImageBox::OnChangeSize, this); scrollbar = new Scrollbar(Point(), Size(), OR_HORZ, &scrollbarPos, 0, 1); scrollbar->SetOrientation(OR_LOWERLEFT); scrollbar->SetStepSize(15); scrollbar->onValueChange.Connect(&ImageBox::OnScrollbarValueChange, this); scrollbar->Hide(); Add(scrollbar); } S::GUI::ImageBox::~ImageBox() { DeleteObject(scrollbar); } S::Int S::GUI::ImageBox::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Rect entryRect = frame; String visibleEntries; Int visibleEntryCount = 0; Int entriesWidth = 0; Int scrollbarHeight = (scrollbar->IsVisible() ? scrollbar->GetHeight() : 0); switch (message) { case SP_PAINT: surface->StartPaint(frame); /* Update scrollbar if necessary. */ entriesWidth = GetEntriesWidth(); if (entriesWidth > GetWidth() - 4) { scrollbar->SetMetrics(Point(1, 18), Size(GetWidth() - 2, scrollbar->GetHeight())); scrollbar->SetRange(0, entriesWidth - (GetWidth() - 4)); scrollbar->SetPageSize(GetWidth() - 4); scrollbar->Show(); scrollbarHeight = scrollbar->GetHeight(); } else { scrollbar->Hide(); scrollbarPos = 0; scrollbarHeight = 0; } /* Set visibility of image entries first. */ entryRect.left = -scrollbarPos; entryRect.right = -scrollbarPos; for (Int i = 0; i < Length(); i++) { ListEntry *entry = GetNthEntry(i); entry->SetVisibleDirect(False); if (entryRect.right + entry->GetWidth() >= 0 && entryRect.left <= GetWidth() - 4) { entry->SetMetrics(Point(entryRect.left + 2, 2), Size(entry->GetWidth(), GetHeight() - 4 - scrollbarHeight)); entry->SetVisibleDirect(True); visibleEntries[visibleEntryCount++] = entry->GetHandle() % 32767 + 1; } entryRect.left += entry->GetWidth(); entryRect.right += entry->GetWidth(); } visibleEntriesString = visibleEntries; /* Now paint the imagebox and all entries. */ if (IsActive()) surface->Box(frame - Size(0, scrollbarHeight), Setup::ClientColor, Rect::Filled); else surface->Box(frame - Size(0, scrollbarHeight), Setup::BackgroundColor, Rect::Filled); surface->Frame(frame, FRAME_DOWN); Widget::Paint(message); surface->EndPaint(); break; case SP_UPDATE: /* Update scrollbar if necessary. */ entriesWidth = GetEntriesWidth(); if ((entriesWidth > GetWidth() - 4 && !scrollbar->IsVisible()) || (entriesWidth <= GetWidth() - 4 && scrollbar->IsVisible())) return Paint(SP_PAINT); scrollbar->SetRange(0, entriesWidth - (GetWidth() - 4)); /* Find visible entries. */ entryRect.left = -scrollbarPos; entryRect.right = -scrollbarPos; for (Int i = 0; i < Length(); i++) { ListEntry *entry = GetNthEntry(i); if (entryRect.right + entry->GetWidth() >= 0 && entryRect.left <= GetWidth() - 4) { visibleEntries[visibleEntryCount++] = entry->GetHandle() % 32767 + 1; } entryRect.left += entry->GetWidth(); entryRect.right += entry->GetWidth(); } /* Check for changes. */ if (visibleEntriesString != visibleEntries) Paint(SP_PAINT); break; } return Success(); } S::GUI::Rect S::GUI::ImageBox::GetVisibleArea() const { if (!IsVisible()) return Widget::GetVisibleArea(); else return Widget::GetVisibleArea() + Point(2, 0) - Size(4, 0); } S::Int S::GUI::ImageBox::GetEntriesWidth() const { Int entriesWidth = 0; for (Int i = 0; i < GetNOfObjects(); i++) { if (GetNthObject(i)->GetObjectType() != ListEntry::classID) continue; entriesWidth += GetNthObject(i)->GetWidth(); } return entriesWidth; } S::Void S::GUI::ImageBox::OnScrollbarValueChange() { Paint(SP_PAINT); } S::Void S::GUI::ImageBox::OnChangeSize(const Size &nSize) { if (scrollbar->IsVisible()) { scrollbar->SetWidth(nSize.cx - 2); scrollbar->SetRange(0, GetEntriesWidth() - (GetWidth() - 4)); scrollbar->SetPageSize(GetWidth() - 4); } } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/image/imageentry.cpp000077500000000000000000000054721516402577000267460ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::GUI::ImageEntry::classID = S::Object::RequestClassID(); S::GUI::ImageEntry::ImageEntry(const Bitmap &iBitmap, const Size &iSize) : ListEntry(NIL) { type = classID; SetSize(iSize); image = new Image(iBitmap, Point(2, 2), iSize - Size(4, 4)); Add(image); onChangeSize.Connect(&ImageEntry::OnChangeSize, this); } S::GUI::ImageEntry::~ImageEntry() { DeleteObject(image); if (IsRegistered() && container != NIL) container->Remove(this); } S::Int S::GUI::ImageEntry::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); Size realSize = GetRealSize(); switch (message) { case SP_PAINT: surface->StartPaint(GetVisibleArea()); surface->Box(Rect(realPos, realSize), Setup::ClientColor, Rect::Filled); image->Paint(SP_PAINT); surface->EndPaint(); break; case SP_MOUSEIN: surface->StartPaint(GetVisibleArea()); surface->Box(Rect(realPos, Size(realSize.cx, 2)), Setup::GradientStartColor, Rect::Filled); surface->Box(Rect(realPos, Size(2, realSize.cy)), Setup::GradientStartColor, Rect::Filled); surface->Box(Rect(realPos + Point(realSize.cx - 2, 0), Size(2, realSize.cy)), Setup::GradientStartColor, Rect::Filled); surface->Box(Rect(realPos + Point(0, realSize.cy - 2), Size(realSize.cx, 2)), Setup::GradientStartColor, Rect::Filled); surface->EndPaint(); break; case SP_MOUSEOUT: surface->StartPaint(GetVisibleArea()); surface->Box(Rect(realPos, Size(realSize.cx, 2)), Setup::ClientColor, Rect::Filled); surface->Box(Rect(realPos, Size(2, realSize.cy)), Setup::ClientColor, Rect::Filled); surface->Box(Rect(realPos + Point(realSize.cx - 2, 0), Size(2, realSize.cy)), Setup::ClientColor, Rect::Filled); surface->Box(Rect(realPos + Point(0, realSize.cy - 2), Size(realSize.cx, 2)), Setup::ClientColor, Rect::Filled); surface->EndPaint(); break; } return Success(); } S::Void S::GUI::ImageEntry::OnChangeSize(const Size &newSize) { image->SetSize(newSize - Size(4, 4)); } S::Bool S::GUI::ImageEntry::IsTypeCompatible(Short compType) const { if (compType == ListEntry::classID) return True; else return ListEntry::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/list/000077500000000000000000000000001516402577000237545ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/list/Makefile000066400000000000000000000005601516402577000254150ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. # Enter object files here: OBJECTS = combobox.o list.o listbox.o listboxheader.o listentry.o listentryseparator.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/list/combobox.cpp000077500000000000000000000161761516402577000263060ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include const S::Short S::GUI::ComboBox::classID = S::Object::RequestClassID(); S::GUI::ComboBox::ComboBox(const Point &iPos, const Size &iSize) { type = classID; listBox = NIL; toolWindow = NIL; listBoxClosed = 0; prevSelectedEntry = 0; SetFont(Font(font.GetName(), Font::DefaultSize, Font::Normal, Font::Normal, Setup::ClientTextColor)); SetMetrics(iPos, iSize); if (GetWidth() == 0) SetWidth(80); if (GetHeight() == 0) SetHeight(19); hotspot = new Hotspot(Point(1, 1), GetSize() - Size(19, 2)); hotspot->onLeftButtonDown.Connect(&ComboBox::OpenListBox, this); buttonHotspot = new HotspotSimpleButton(Point(16, 3), Size(13, GetHeight() - 6)); buttonHotspot->SetOrientation(OR_UPPERRIGHT); buttonHotspot->onLeftButtonDown.Connect(&ComboBox::OpenListBox, this); Add(hotspot); Add(buttonHotspot); onChangeSize.Connect(&ComboBox::OnChangeSize, this); onSelectEntry.Connect(&ComboBox::OnSelectEntry, this); onLoseFocus.Connect(&ComboBox::CloseListBox, this); } S::GUI::ComboBox::~ComboBox() { DeleteObject(hotspot); DeleteObject(buttonHotspot); CloseListBox(); } S::Int S::GUI::ComboBox::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); if (GetSelectedEntry() == NIL && !(flags & CB_HOTSPOTONLY)) { if (GetNthEntry(0) != NIL) ((ListEntry *) GetNthEntry(0))->Select(); } if (flags & CB_HOTSPOTONLY) hotspot->Deactivate(); else hotspot->Activate(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); switch (message) { case SP_PAINT: surface->StartPaint(frame); if (!(flags & CB_HOTSPOTONLY)) { if (IsActive()) surface->Box(frame, Setup::ClientColor, Rect::Filled); else surface->Box(frame, Setup::BackgroundColor, Rect::Filled); surface->Frame(frame, FRAME_DOWN); } surface->Box(frame + Point(frame.GetWidth() - frame.GetHeight() + 1, 1) - Size(frame.GetWidth() - frame.GetHeight() + 2, 2), Setup::BackgroundColor, Rect::Filled); surface->Frame(frame + Point(frame.GetWidth() - frame.GetHeight() + 1, 1) - Size(frame.GetWidth() - frame.GetHeight() + 2, 2), FRAME_UP); { Int height = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); Point lineStart = Point(frame.right - (frame.GetHeight() - 1) / 2 - height + (IsRightToLeft() ? 1 : 0), frame.top + (frame.GetHeight() - height) / 2); Point lineEnd = lineStart + Point(height * 2 - 1, 0); for (Int i = 0; i < height; i++) { if (IsActive()) surface->Line(lineStart, lineEnd, Setup::TextColor); else surface->Line(lineStart, lineEnd, Setup::InactiveTextColor); lineStart += Point(1, 1); lineEnd += Point(-1, 1); } } if (!(flags & CB_HOTSPOTONLY)) { for (Int i = 0; i < Length(); i++) { ListEntry *entry = GetNthEntry(i); if (entry->IsSelected()) { String entryText = entry->GetText(); if (entryText.Contains(ListEntry::tabDelimiter)) entryText = entryText.Head(entryText.Find(ListEntry::tabDelimiter)); surface->SetText(entryText, frame + Point(3 * surface->GetSurfaceDPI() / 96.0, Math::Ceil(Float(frame.GetHeight() - entry->GetFont().GetScaledTextSizeY()) / 2) - 1) - Size(frame.GetHeight() + 2, 0), entry->GetFont()); if (entry->GetUnscaledTextWidth() >= GetWidth() - 22) SetTooltipText(entryText); else SetTooltipText(NIL); } } } surface->EndPaint(); break; } return Success(); } S::Void S::GUI::ComboBox::OnSelectEntry(ListEntry *entry) { if (listBox != NIL) CloseListBox(); if (prevSelectedEntry != entry->GetHandle()) { Paint(SP_PAINT); if (flags & CB_HOTSPOTONLY) entry->Deselect(); prevSelectedEntry = entry->GetHandle(); } } S::Void S::GUI::ComboBox::OpenListBox() { if (listBox != NIL) return; Window *window = container->GetContainerWindow(); Surface *surface = GetDrawSurface(); if (S::System::System::Clock() - listBoxClosed < 100) { if (window->IsMouseOn(Rect(buttonHotspot->GetRealPosition(), buttonHotspot->GetRealSize()))) buttonHotspot->Paint(SP_MOUSEUP); return; } Rect monitor = System::Screen::GetActiveScreenWorkArea(); Float scaleFactor = surface->GetSurfaceDPI() / 96.0; Size listBoxSize = Size(GetWidth(), 16 * Math::Min(Length(), Math::Max(5, Math::Min(16, Length() / 3))) + 4); Point listBoxPos = Point(GetRealPosition() + Point(0, GetRealSize().cy)); if (window->GetY() + listBoxPos.y + Math::Round(listBoxSize.cy * scaleFactor) >= monitor.bottom) listBoxPos = Point(GetRealPosition() - Point(0, Math::Round(listBoxSize.cy * scaleFactor))); listBox = new ListBox(Point(), listBoxSize); listBox->onSelectEntry.Connect(&onSelectEntry); toolWindow = new ToolWindow(listBoxPos, listBoxSize); toolWindow->onLoseFocus.Connect(&ComboBox::CloseListBox, this); window->onChangePosition.Connect(&ComboBox::CloseListBox, this); window->onChangeSize.Connect(&ComboBox::CloseListBox, this); listBox->SetFlags(LF_ALLOWRESELECT | LF_HIDEHEADER); listBox->AddTab(NIL, 32768); ListEntry *selectedEntry = GetSelectedEntry(); if (selectedEntry != NIL) prevSelectedEntry = selectedEntry->GetHandle(); for (Int i = 0; i < Length(); i++) { ListEntry *entry = GetNthEntry(i); entry->SetRegisteredFlag(False); listBox->Add(entry); if (entry->GetUnscaledTextWidth() >= listBoxSize.cx - (listBoxSize.cy < 16 * Length() ? 22 : 5)) entry->SetTooltipText(entry->GetText()); else entry->SetTooltipText(NIL); entry->Activate(); } toolWindow->Add(listBox); Add(toolWindow); } S::Void S::GUI::ComboBox::CloseListBox() { if (listBox == NIL) return; Window *window = container->GetContainerWindow(); toolWindow->onLoseFocus.Disconnect(&ComboBox::CloseListBox, this); toolWindow->Close(); window->onChangePosition.Disconnect(&ComboBox::CloseListBox, this); window->onChangeSize.Disconnect(&ComboBox::CloseListBox, this); listBox->RemoveAllEntries(); for (Int i = 0; i < Length(); i++) { ListEntry *entry = GetNthEntry(i); entry->SetTooltipText(NIL); entry->Hide(); entry->Deactivate(); entry->SetRegisteredFlag(True); entry->SetContainer(this); } toolWindow->Remove(listBox); Remove(toolWindow); DeleteObject(listBox); DeleteObject(toolWindow); listBox = NIL; toolWindow = NIL; listBoxClosed = S::System::System::Clock(); } S::Void S::GUI::ComboBox::OnChangeSize(const Size &nSize) { hotspot->SetSize(nSize - Size(19, 2)); buttonHotspot->SetHeight(nSize.cy - 6); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/list/list.cpp000077500000000000000000000054601516402577000254430ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include const S::Short S::GUI::List::classID = S::Object::RequestClassID(); S::GUI::List::List() { type = classID; onSelectEntry.SetParentObject(this); onMarkEntry.SetParentObject(this); } S::GUI::List::~List() { } S::GUI::ListEntry *S::GUI::List::AddEntry(const String &text, Bool marked) { ListEntry *newEntry = new ListEntry(text); newEntry->SetMark(marked); if (Add(newEntry) == Success()) { createdEntry.Set(newEntry->GetHandle(), True); return newEntry; } DeleteObject(newEntry); return NIL; } S::GUI::ListEntry *S::GUI::List::AddSeparator() { ListEntrySeparator *newEntry = new ListEntrySeparator(); if (Add(newEntry) == Success()) { createdEntry.Set(newEntry->GetHandle(), True); return newEntry; } DeleteObject(newEntry); return NIL; } S::Int S::GUI::List::Add(Widget *widget) { if (widget == NIL) return Error(); if (!widget->IsRegistered()) { if (widget->GetObjectType() == ListEntry::classID) widget->Hide(); return Container::Add(widget); } return Error(); } S::Int S::GUI::List::SelectEntry(const ListEntry *entryToSelect) { foreach (Entry *entry, elementOrder) { if (entry != entryToSelect) continue; ((ListEntry *) entry)->Select(); return Success(); } return Error(); } S::GUI::ListEntry *S::GUI::List::GetSelectedEntry() const { foreach (Entry *entry, elementOrder) { if (((ListEntry *) entry)->IsSelected()) return (ListEntry *) entry; } return NIL; } S::Int S::GUI::List::SelectNthEntry(Int n) { if (n < 0 || n >= Length()) return Error(); ListEntry *entry = GetNthEntry(n); if (!entry->IsSelected()) entry->Select(); return Success(); } S::Int S::GUI::List::GetSelectedEntryNumber() const { for (Int i = 0; i < elementOrder.Length(); i++) { ListEntry *entry = (ListEntry *) elementOrder.GetNth(i); if (entry->IsSelected()) return i; } return -1; } S::Int S::GUI::List::GetEntryNumber(const String &entryText) const { for (Int i = 0; i < elementOrder.Length(); i++) { ListEntry *entry = (ListEntry *) elementOrder.GetNth(i); if (entry->GetText() == entryText) return i; } return -1; } S::GUI::ListEntry *S::GUI::List::GetEntry(const String &entryText) const { return GetNthEntry(GetEntryNumber(entryText)); } S::Int S::GUI::List::SelectEntry(const String &entryText) { return SelectNthEntry(GetEntryNumber(entryText)); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/list/listbox.cpp000077500000000000000000000223031516402577000261470ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::ListBox::classID = S::Object::RequestClassID(); S::GUI::ListBox::ListBox(const Point &iPos, const Size &iSize) { type = classID; scrollbar = NIL; scrollbarPos = 0; SetFont(Font(font.GetName(), Font::DefaultSize, Font::Normal, Font::Normal, Setup::ClientTextColor)); SetBackgroundColor(Setup::ClientColor); SetMetrics(iPos, iSize); if (GetWidth() == 0) SetWidth(120); if (GetHeight() == 0) SetHeight(80); onChangeSize.Connect(&ListBox::OnChangeSize, this); scrollbar = new Scrollbar(Point(), Size(), OR_VERT, &scrollbarPos, 0, 1); scrollbar->SetOrientation(OR_UPPERRIGHT); scrollbar->SetStepSize(16); scrollbar->onValueChange.Connect(&ListBox::OnScrollbarValueChange, this); scrollbar->Hide(); header = new ListBoxHeader(Point(1, 1), Size(GetWidth() - 2, 16)); header->onClickTab.Connect(&onClickTab); header->Hide(); Add(scrollbar); Add(header); } S::GUI::ListBox::~ListBox() { DeleteObject(scrollbar); DeleteObject(header); } S::Int S::GUI::ListBox::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Rect entryRect = frame; String visibleEntries; Int visibleEntryCount = 0; ListEntry *lastVisibleEntry = NIL; if (GetNOfTabs() > 0 && !(flags & LF_HIDEHEADER)) header->Show(); else header->Hide(); Int entriesHeight = 0; Int headerHeight = (header->IsVisible() ? header->GetHeight() : 0); Int scrollbarWidth = (scrollbar->IsVisible() ? scrollbar->GetWidth() : 0); switch (message) { case SP_PAINT: surface->StartPaint(frame); /* Update scrollbar if necessary. */ entriesHeight = GetEntriesHeight(); if (entriesHeight > GetHeight() - headerHeight - 4 && !(flags & LF_HIDESCROLLBAR)) { scrollbar->SetMetrics(Point(18, 1 + headerHeight), Size(scrollbar->GetWidth(), GetHeight() - 2 - headerHeight)); scrollbar->SetRange(0, entriesHeight - (GetHeight() - 4 - headerHeight)); scrollbar->SetPageSize(GetHeight() - 4 - headerHeight); scrollbar->Show(); scrollbarWidth = scrollbar->GetWidth(); } else { scrollbar->Hide(); scrollbarPos = 0; scrollbarWidth = 0; } /* Set visibility of list entries first. */ entryRect.top = -scrollbarPos; entryRect.bottom = -scrollbarPos; for (Int i = 0; i < Length(); i++) { ListEntry *entry = GetNthEntry(i); entry->SetVisibleDirect(False); if (entryRect.bottom + entry->GetHeight() >= 0 && entryRect.top <= GetHeight() - headerHeight - 4) { entry->SetMetrics(Point(2, entryRect.top + 2 + headerHeight), Size(GetWidth() - 4 - scrollbarWidth, entry->GetHeight())); entry->SetVisibleDirect(True); visibleEntries[visibleEntryCount++] = entry->GetHandle() % 32767 + 1; } entryRect.top += entry->GetHeight(); entryRect.bottom += entry->GetHeight(); } visibleEntriesString = visibleEntries; /* Now paint the listbox and all entries. */ if (IsActive()) surface->Box(frame + Point(0, headerHeight) - Size(scrollbarWidth, headerHeight), Setup::ClientColor, Rect::Filled); else surface->Box(frame + Point(0, headerHeight) - Size(scrollbarWidth, headerHeight), Setup::BackgroundColor, Rect::Filled); surface->Frame(frame, FRAME_DOWN); Widget::Paint(message); surface->EndPaint(); break; case SP_UPDATE: /* Update scrollbar if necessary. */ entriesHeight = GetEntriesHeight(); if ((entriesHeight > GetHeight() - headerHeight - 4 && !scrollbar->IsVisible() && !(flags & LF_HIDESCROLLBAR)) || (entriesHeight <= GetHeight() - headerHeight - 4 && scrollbar->IsVisible() )) return Paint(SP_PAINT); scrollbar->SetRange(0, entriesHeight - (GetHeight() - 4 - headerHeight)); /* Find visible entries. */ entryRect.top = -scrollbarPos; entryRect.bottom = -scrollbarPos; for (Int i = 0; i < Length(); i++) { ListEntry *entry = GetNthEntry(i); entry->SetVisibleDirect(False); if (entryRect.bottom + entry->GetHeight() >= 0 && entryRect.top <= GetHeight() - headerHeight - 4) { entry->SetMetrics(Point(2, entryRect.top + 2 + headerHeight), Size(GetWidth() - 4 - scrollbarWidth, entry->GetHeight())); entry->SetVisibleDirect(True); lastVisibleEntry = entry; visibleEntries[visibleEntryCount++] = entry->GetHandle() % 32767 + 1; } entryRect.top += entry->GetHeight(); entryRect.bottom += entry->GetHeight(); if (entryRect.top > GetHeight() - headerHeight - 4) break; } /* Check for changes. */ if (visibleEntriesString != visibleEntries) { /* Draw added entry only if it was added to the end. */ if (visibleEntries.StartsWith(visibleEntriesString) && visibleEntries.Length() == visibleEntriesString.Length() + 1) lastVisibleEntry->Paint(SP_PAINT); /* Nothing needs to be done if last entry was removed. */ else if (visibleEntriesString.StartsWith(visibleEntries) && visibleEntriesString.Length() == visibleEntries.Length() + 1) ; /* Redraw the whole list if something else changed. */ else Paint(SP_PAINT); visibleEntriesString = visibleEntries; } break; } return Success(); } S::Int S::GUI::ListBox::ScrollUp(Int n) { if (n == ScrollToTop) scrollbar->SetValue(0); else scrollbar->SetValue(scrollbarPos - scrollbar->GetStepSize()); return Success(); } S::Int S::GUI::ListBox::ScrollDown(Int n) { if (n == ScrollToBottom) scrollbar->SetValue(2147483647); else scrollbar->SetValue(scrollbarPos + scrollbar->GetStepSize()); return Success(); } S::Int S::GUI::ListBox::DragSelectedEntry(Bool upDown) { if (!(flags & LF_ALLOWREORDER)) return Error(); /* Get entry numbers to switch and check. */ Int selectedEntryNumber = GetSelectedEntryNumber(); Int newEntryNumber = selectedEntryNumber; Int checkEntryNumber = selectedEntryNumber; if (upDown) { newEntryNumber = Math::Max(0, selectedEntryNumber - 1); checkEntryNumber = Math::Max(0, newEntryNumber - 1); } else { newEntryNumber = Math::Min(selectedEntryNumber + 1, Length() - 1); checkEntryNumber = Math::Min(newEntryNumber + 1, Length() - 1); } /* Check whether entry should be moved. */ if (selectedEntryNumber != newEntryNumber) { Int oldScrollbarPos = scrollbarPos; /* Check whether to scroll the whole list. */ ListEntry *checkEntry = GetNthEntry(checkEntryNumber); if (!checkEntry->IsVisible() || checkEntry->GetVisibleArea().GetHeight() <= 2) { if (upDown) scrollbarPos -= scrollbar->GetStepSize(); else scrollbarPos += scrollbar->GetStepSize(); } /* Move entry to new position. */ MoveEntry(selectedEntryNumber, newEntryNumber); /* Redraw the list. */ Surface *surface = GetDrawSurface(); ListEntry *oldEntry = GetNthEntry(selectedEntryNumber); surface->StartPaint(Rect(GetRealPosition(), GetRealSize())); Paint(SP_PAINT); oldEntry->Process(SM_MOUSEMOVE, 0, 0); surface->EndPaint(); /* If list was scrolled, delay next action by 100ms. */ if (scrollbarPos != oldScrollbarPos) System::System::Sleep(100); } else { if (upDown) ScrollUp(ScrollToTop); else ScrollDown(ScrollToBottom); } return Success(); } S::GUI::Rect S::GUI::ListBox::GetVisibleArea() const { Int headerHeight = (header->IsVisible() ? header->GetRealSize().cy : 0); if (!IsVisible()) return Widget::GetVisibleArea(); else return Widget::GetVisibleArea() + Point(0, 2 + headerHeight) - Size(0, 4 + headerHeight); } S::Int S::GUI::ListBox::GetEntriesHeight() const { Int entriesHeight = 0; for (Int i = 0; i < Length(); i++) { entriesHeight += GetNthEntry(i)->GetHeight(); } return entriesHeight; } S::Void S::GUI::ListBox::OnScrollbarValueChange() { if (!IsVisible()) return; /* Redraw only the list entries. */ Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Int headerHeight = (header->IsVisible() ? header->GetRealSize().cy : 0); Int scrollbarWidth = (scrollbar->IsVisible() ? scrollbar->GetRealSize().cx : 0); surface->StartPaint(frame + Point(2, 2 + headerHeight) - Size(4 + scrollbarWidth, 4 + headerHeight)); Paint(SP_PAINT); surface->EndPaint(); } S::Void S::GUI::ListBox::OnChangeSize(const Size &nSize) { if (scrollbar->IsVisible()) { Int headerHeight = (header->IsVisible() ? header->GetHeight() : 0); scrollbar->SetHeight(nSize.cy - 2 - headerHeight); scrollbar->SetRange(0, GetEntriesHeight() - (GetHeight() - 4 - headerHeight)); scrollbar->SetPageSize(GetHeight() - 4 - headerHeight); } header->SetWidth(nSize.cx - 2); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/list/listboxheader.cpp000077500000000000000000000201441516402577000273210ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include const S::Short S::GUI::ListBoxHeader::classID = S::Object::RequestClassID(); S::GUI::ListBoxHeader::ListBoxHeader(const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { moveTab = -1; draggingTab = False; moveTabStartWidth = 0; lastTabStartWidth = 0; type = classID; font.SetWeight(Font::Bold); dragHotspot = new Hotspot(Point(0, 0), GetSize()); dragHotspot->SetIndependent(True); dragHotspot->onMouseDragStart.Connect(&ListBoxHeader::OnMouseDragStart, this); dragHotspot->onMouseDrag.Connect(&ListBoxHeader::OnMouseDrag, this); dragHotspot->onMouseDragEnd.Connect(&ListBoxHeader::OnMouseDragEnd, this); dragHotspot->onLeftButtonClick.Connect(&ListBoxHeader::OnLeftButtonClick, this); Add(dragHotspot); onChangeSize.Connect(&ListBoxHeader::OnChangeSize, this); } S::GUI::ListBoxHeader::~ListBoxHeader() { DeleteObject(dragHotspot); } S::Int S::GUI::ListBoxHeader::EnableLocking(Bool enable) { if (enable) { tabNames.EnableLocking(); tabWidths.EnableLocking(); tabOrientations.EnableLocking(); tabChecked.EnableLocking(); } else { tabNames.DisableLocking(); tabWidths.DisableLocking(); tabOrientations.DisableLocking(); tabChecked.DisableLocking(); } return Widget::EnableLocking(enable); } S::Int S::GUI::ListBoxHeader::AddTab(const String &iTabName, Int iTabWidth, Int iTabOrientation) { tabNames.Add(iTabName); tabWidths.Add(iTabWidth); tabOrientations.Add(iTabOrientation); tabChecked.Add(False); OnChangeSize(GetSize()); return Success(); } S::Int S::GUI::ListBoxHeader::RemoveAllTabs() { tabNames.RemoveAll(); tabWidths.RemoveAll(); tabOrientations.RemoveAll(); tabChecked.RemoveAll(); OnChangeSize(GetSize()); return Success(); } S::Int S::GUI::ListBoxHeader::GetNOfTabs() const { return tabWidths.Length(); } S::Int S::GUI::ListBoxHeader::GetNthTabOffset(Int n) const { if (n >= tabWidths.Length()) return -1; Int offset = 0; for (Int i = 0; i < n; i++) { offset += (Int) Math::Abs(tabWidths.GetNth(i)); } return offset; } S::Int S::GUI::ListBoxHeader::GetNthTabWidth(Int n) const { return (Int) Math::Abs(tabWidths.GetNth(n)); } S::Int S::GUI::ListBoxHeader::GetNthTabOrientation(Int n) const { return (Int) Math::Abs(tabOrientations.GetNth(n)); } S::Int S::GUI::ListBoxHeader::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->Box(frame, Setup::BackgroundColor, Rect::Filled); surface->Frame(frame, FRAME_UP); for (Int i = 0; i < tabWidths.Length(); i++) { frame.right = (Int) Math::Min(frame.left + Math::Abs(Math::Round(tabWidths.GetNth(i) * surface->GetSurfaceDPI() / 96.0)), realPos.x + GetRealSize().cx); surface->Box(frame, Setup::BackgroundColor, Rect::Filled); surface->Frame(frame, FRAME_UP); Font nFont = font; if (!IsActive()) nFont.SetColor(Setup::InactiveTextColor); surface->SetText(tabNames.GetNth(i), frame + Point(3, Math::Ceil(Float(frame.GetHeight() - font.GetScaledTextSizeY()) / 2) - 1) - Size(5, 0), nFont); frame.left += (Int) Math::Abs(Math::Round(tabWidths.GetNth(i) * surface->GetSurfaceDPI() / 96.0)); } } break; } return Success(); } S::Int S::GUI::ListBoxHeader::Process(Int message, Int wParam, Int lParam) { if (!IsRegistered()) return Error(); if (!IsActive() || !IsVisible()) return Success(); switch (message) { case SM_MOUSEMOVE: if (draggingTab) break; { Window *window = GetContainerWindow(); Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Rect frame = Rect(realPos, realSize); frame.left = realPos.x - 2; for (Int i = 0; i < tabWidths.Length() - 1; i++) { frame.left += (Int) Math::Abs(Math::Round(tabWidths.GetNth(i) * surface->GetSurfaceDPI() / 96.0)); frame.right = frame.left + 4; if (window->IsMouseOn(frame)) { if (moveTab != i) { moveTab = i; Input::Pointer::SetCursor(window, Input::Pointer::CursorHSize); } } else if (moveTab == i) { moveTab = -1; Input::Pointer::SetCursor(window, Input::Pointer::CursorArrow); } } frame.left = realPos.x + 1; frame.top++; frame.bottom--; for (Int j = 0; j < tabWidths.Length(); j++) { frame.right = (Int) Math::Min(frame.left + Math::Abs(Math::Round(tabWidths.GetNth(j) * surface->GetSurfaceDPI() / 96.0)) - 2, realPos.x + GetRealSize().cx - 1); if (window->IsMouseOn(frame) && !tabChecked.GetNth(j) && moveTab == -1) { surface->StartPaint(frame); surface->Box(frame, Setup::LightGrayColor, Rect::Filled); surface->SetText(tabNames.GetNth(j), frame + Point(2, Math::Ceil(Float(frame.GetHeight() - font.GetScaledTextSizeY()) / 2) - 1) - Size(2, 0), font); surface->EndPaint(); tabChecked.Set(tabChecked.GetNthIndex(j), True); } else if ((!window->IsMouseOn(frame) || moveTab != -1) && tabChecked.GetNth(j)) { surface->StartPaint(frame); surface->Box(frame, Setup::BackgroundColor, Rect::Filled); surface->SetText(tabNames.GetNth(j), frame + Point(2, Math::Ceil(Float(frame.GetHeight() - font.GetScaledTextSizeY()) / 2) - 1) - Size(2, 0), font); surface->EndPaint(); tabChecked.Set(tabChecked.GetNthIndex(j), False); } frame.left += (Int) Math::Abs(Math::Round(tabWidths.GetNth(j) * surface->GetSurfaceDPI() / 96.0)); } } break; } return Widget::Process(message, wParam, lParam); } S::Void S::GUI::ListBoxHeader::OnLeftButtonClick(const Point &mousePos) { if (draggingTab) return; Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); for (Int n = 0; n < GetNOfTabs(); n++) { if (mousePos.x - realPos.x >= GetNthTabOffset(n) * surface->GetSurfaceDPI() / 96.0 && mousePos.x - realPos.x < (GetNthTabOffset(n) + GetNthTabWidth(n)) * surface->GetSurfaceDPI() / 96.0) { onClickTab.Emit(n); break; } } } S::Void S::GUI::ListBoxHeader::OnMouseDragStart(const Point &mousePos) { if (moveTab == -1) return; startMousePos = mousePos; moveTabStartWidth = tabWidths.GetNth(moveTab); lastTabStartWidth = tabWidths.GetNth(tabWidths.Length() - 1); draggingTab = True; } S::Void S::GUI::ListBoxHeader::OnMouseDrag(const Point &mousePos) { if (!draggingTab) return; Int bias = Math::Round((startMousePos.x - mousePos.x) * 96.0 / Surface().GetSurfaceDPI()); if (bias != 0) { tabWidths.SetNth(moveTab, (Int) Math::Max(Math::Abs(moveTabStartWidth) - bias, 1) * Math::Sign(moveTabStartWidth)); tabWidths.SetNth(tabWidths.Length() - 1, (Int) Math::Max(Math::Abs(lastTabStartWidth) + bias, 1) * Math::Sign(lastTabStartWidth)); OnChangeSize(GetSize()); container->Paint(SP_PAINT); } } S::Void S::GUI::ListBoxHeader::OnMouseDragEnd(const Point &mousePos) { draggingTab = False; } S::Void S::GUI::ListBoxHeader::OnChangeSize(const Size &nSize) { Int varSizeTabs = 0; Int sumFixedTabSizes = 0; for (Int i = 0; i < tabWidths.Length(); i++) { if (tabWidths.GetNth(i) <= 0) varSizeTabs++; else sumFixedTabSizes += tabWidths.GetNth(i); } if (varSizeTabs > 0) { for (Int i = 0; i < tabWidths.Length(); i++) { if (tabWidths.GetNth(i) <= 0) tabWidths.SetNth(i, -Math::Max(0, (GetWidth() - sumFixedTabSizes) / varSizeTabs)); } } dragHotspot->SetSize(nSize); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/list/listentry.cpp000077500000000000000000000206021516402577000265200ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include S::Signal2 S::GUI::ListEntry::internalOnSelectEntry; const S::Short S::GUI::ListEntry::classID = S::Object::RequestClassID(); const S::String S::GUI::ListEntry::tabDelimiter = "\v"; S::GUI::ListEntry::ListEntry(const String &iText) { type = classID; selected = False; marked = False; text = iText; font.SetColor(Setup::ClientTextColor); ComputeTextSize(); hotspot = new Hotspot(Point(), GetSize()); markHotspot = new Hotspot(Point(2, 3), Size(9, 9)); hotspot->onLeftButtonDown.Connect(&ListEntry::OnSelectEntry, this); markHotspot->onLeftButtonDown.Connect(&ListEntry::OnClickMarkHotspot, this); hotspot->onMouseDrag.Connect(&ListEntry::InitDrag, this); Add(hotspot); Add(markHotspot); SetSize(Size(100, 16)); internalOnSelectEntry.Connect(&ListEntry::OnSelectOtherEntry, this); onChangeSize.Connect(&Hotspot::SetSize, hotspot); } S::GUI::ListEntry::~ListEntry() { internalOnSelectEntry.Disconnect(&ListEntry::OnSelectOtherEntry, this); DeleteObject(hotspot); DeleteObject(markHotspot); } S::Int S::GUI::ListEntry::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Widget *listBox = container; Font nFont = font; Bool gotTabs = False; switch (message) { case SP_PAINT: case SP_MOUSEIN: case SP_MOUSEOUT: if (mouseOver) nFont.SetColor(Setup::GradientTextColor); if (!IsActive()) nFont.SetColor(Setup::InactiveTextColor); gotTabs = text.Contains(tabDelimiter); surface->StartPaint(GetVisibleArea()); /* Draw background and frame. */ if (mouseOver) surface->Gradient(frame, Setup::GradientStartColor, Setup::GradientEndColor, OR_HORZ); else surface->Box(frame, IsActive() ? Setup::ClientColor : Setup::BackgroundColor, Rect::Filled); if (selected) surface->Box(frame, Setup::ClientTextColor, Rect::Dotted); /* Draw checkbox if necessary. */ if (container->GetFlags() & LF_MULTICHECKBOX) { Rect cbRect = Rect(GetRealPosition() + Point(2, 3) * surface->GetSurfaceDPI() / 96.0, Size(9, 9) * surface->GetSurfaceDPI() / 96.0); if (cbRect.top <= cbRect.bottom - 1) { surface->Box(cbRect, Setup::ClientColor, Rect::Filled); surface->Box(cbRect, Setup::InactiveTextColor, Rect::Outlined); if (marked && cbRect.top <= cbRect.bottom - 3) { Color lightColor = Setup::InactiveTextColor; Color darkColor = Setup::ClientTextColor; if (!IsActive()) darkColor = Setup::InactiveTextColor; Point p1 = Point(cbRect.left + 2 + (IsRightToLeft() ? 1 : 0), cbRect.top + 2); Point p2 = Point(cbRect.right - 2 + (IsRightToLeft() ? 1 : 0), cbRect.bottom - 2); surface->Line(p1 + Point(0, 0), p2 + Point(0, 0), darkColor); surface->Line(p1 + Point(1, 0), p2 + Point(0, -1), lightColor); surface->Line(p1 + Point(0, 1), p2 + Point(-1, 0), lightColor); p1 = Point(cbRect.right - 3 + (IsRightToLeft() ? 1 : 0), cbRect.top + 2); p2 = Point(cbRect.left + 1 + (IsRightToLeft() ? 1 : 0), cbRect.bottom - 2); surface->Line(p1 + Point(0, 0), p2 + Point(0, 0), darkColor); surface->Line(p1 + Point(0, 1), p2 + Point(1, 0), lightColor); surface->Line(p1 + Point(-1, 0), p2 + Point(0, -1), lightColor); } } } /* Get parent ListBox widget. */ while (listBox->GetObjectType() != ListBox::classID) { listBox = listBox->GetContainer(); if (listBox == NIL) break; } /* Draw entry text. */ Int lineHeight = scaledTextSize.cy; if (text.Contains("\n")) lineHeight = nFont.GetScaledTextSizeY(); if (listBox != NIL && ((ListBox *) listBox)->GetNOfTabs() > 0 && gotTabs) { for (Int i = 0; i < ((ListBox *) listBox)->GetNOfTabs(); i++) { Rect rect = Rect(GetRealPosition() + Point(0, Math::Ceil(Float(frame.GetHeight() - lineHeight) / 2) - 2) + Point(1, 1) * surface->GetSurfaceDPI() / 96.0 + Point(i > 0 && listBox != container ? listBox->GetRealPosition().x - container->GetRealPosition().x + 2 : 0, 0), GetRealSize() - Size(1, 1) * surface->GetSurfaceDPI() / 96.0 * 2 - Size(1, 0)); rect.left += Math::Round(((ListBox *) listBox)->GetNthTabOffset(i) * surface->GetSurfaceDPI() / 96.0); rect.left += (i == 0 ? (container->GetFlags() & LF_MULTICHECKBOX ? Math::Round(12 * surface->GetSurfaceDPI() / 96.0) : 0) : 0); if (((ListBox *) listBox)->GetNOfTabs() >= i + 2) rect.right = rect.left + (Math::Round(((ListBox *) listBox)->GetNthTabOffset(i + 1) * surface->GetSurfaceDPI() / 96.0) - Math::Round(((ListBox *) listBox)->GetNthTabOffset(i) * surface->GetSurfaceDPI() / 96.0)) - (i == 0 ? (container->GetFlags() & LF_MULTICHECKBOX ? Math::Round(12 * surface->GetSurfaceDPI() / 96.0) : 0) : 0) - Math::Round(1 * surface->GetSurfaceDPI() / 96.0) * 2 - 1; else if (((ListBox *) listBox)->GetNthTabOrientation(i) == OR_RIGHT) rect.right += 1; String tabText = GetNthTabText(i); if (((ListBox *) listBox)->GetNthTabOrientation(i) == OR_RIGHT) { rect.left = Math::Max(rect.left, rect.right - nFont.GetScaledTextSizeX(tabText) - 1); } surface->SetText(tabText, rect, nFont); } } else { surface->SetText(text, frame + Point(0, Math::Ceil(Float(frame.GetHeight() - lineHeight) / 2) - 2) + Point(1, 1) * surface->GetSurfaceDPI() / 96.0 + Point(container->GetFlags() & LF_MULTICHECKBOX ? Math::Round(12 * surface->GetSurfaceDPI() / 96.0) : 0, 0) - Size(1, 1) * surface->GetSurfaceDPI() / 96.0 * 2 - Size(container->GetFlags() & LF_MULTICHECKBOX ? Math::Round(12 * surface->GetSurfaceDPI() / 96.0) : 0, 0), nFont); } Widget::Paint(SP_PAINT); surface->EndPaint(); return Success(); } return Widget::Paint(message); } S::String S::GUI::ListEntry::GetNthTabText(Int i) const { String tabText; Int tabCount = 0; for (Int p = 0; p < text.Length(); p++) { if (tabCount == i) { for (Int q = p; q < text.Length(); q++) { if (text[q] == tabDelimiter[0]) break; tabText[q - p] = text[q]; } break; } if (text[p] == tabDelimiter[0]) tabCount++; } return tabText; } S::Int S::GUI::ListEntry::SetMark(Bool nMarked) { if (nMarked == marked) return Success(); marked = nMarked; if (IsRegistered()) { Paint(SP_PAINT); ((List *) container)->onMarkEntry.Emit(this); } onToggleMark.Emit(marked); return Success(); } S::Int S::GUI::ListEntry::Select() { selected = True; internalOnSelectEntry.Emit(container->GetHandle(), GetHandle()); Paint(SP_PAINT); ((List *) container)->onSelectEntry.Emit(this); onSelect.Emit(); return Success(); } S::Int S::GUI::ListEntry::Deselect() { selected = False; Paint(SP_PAINT); onDeselect.Emit(); return Success(); } S::Void S::GUI::ListEntry::InitDrag() { if (container->GetObjectType() == ListBox::classID) { Point mousePos = container->GetContainerWindow()->GetMousePosition(); Point entryPos = GetRealPosition(); Size entrySize = GetRealSize(); if (mousePos.y < entryPos.y ) ((ListBox *) container)->DragSelectedEntry(True); else if (mousePos.y >= entryPos.y + entrySize.cy) ((ListBox *) container)->DragSelectedEntry(False); } } S::Void S::GUI::ListEntry::OnClickMarkHotspot() { SetMark(!marked); } S::Void S::GUI::ListEntry::OnSelectEntry() { if (!selected || Binary::IsFlagSet(container->GetFlags(), LF_ALLOWRESELECT)) Select(); } S::Void S::GUI::ListEntry::OnSelectOtherEntry(Int containerHandle, Int handle) { if (!IsRegistered()) return; if (container->GetHandle() == containerHandle && GetHandle() != handle && selected) Deselect(); } S::Bool S::GUI::ListEntry::IsTypeCompatible(Short compType) const { if (compType == Entry::classID) return True; else return Entry::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/list/listentryseparator.cpp000077500000000000000000000031701516402577000304420ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::GUI::ListEntrySeparator::classID = S::Object::RequestClassID(); S::GUI::ListEntrySeparator::ListEntrySeparator() : ListEntry(NIL) { type = classID; font.SetColor(Setup::InactiveTextColor); SetHeight(3); Remove(hotspot); Remove(markHotspot); internalOnSelectEntry.Disconnect(&ListEntry::OnSelectOtherEntry, this); } S::GUI::ListEntrySeparator::~ListEntrySeparator() { if (IsRegistered() && container != NIL) container->Remove(this); } S::Int S::GUI::ListEntrySeparator::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->Box(frame + Point(4, 1) - Size(8, 2), font.GetColor(), Rect::Filled); } } return Widget::Paint(message); } S::Bool S::GUI::ListEntrySeparator::IsTypeCompatible(Short compType) const { if (compType == ListEntry::classID) return True; else return ListEntry::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/000077500000000000000000000000001516402577000237455ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/Makefile000066400000000000000000000010571516402577000254100ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = menu.o menubar.o menubarentry.o menuentry.o micromenu.o popupmenu.o popupmenuentry.o popupmenuentrycheck.o popupmenuentryoption.o ifeq ($(BUILD_OSX),True) OBJECTS += menubar_cocoa.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/menu.cpp000077500000000000000000000011721516402577000254210ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include const S::Short S::GUI::Menu::classID = S::Object::RequestClassID(); S::GUI::Menu::Menu() { type = classID; } S::GUI::Menu::~Menu() { } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/menubar.cpp000077500000000000000000000156451516402577000261200ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #ifdef __APPLE__ # include #endif #ifdef __WIN32__ # include #endif const S::Short S::GUI::Menubar::classID = S::Object::RequestClassID(); S::GUI::Menubar::Menubar() { type = classID; orientation = OR_TOP; subtype = WO_SEPARATOR; #ifdef __APPLE__ menubarCocoa = NIL; #endif SetSize(Size(18, 18)); onRegister.Connect(&Menubar::OnRegister, this); onUnregister.Connect(&Menubar::OnUnregister, this); } S::GUI::Menubar::~Menubar() { } S::GUI::MenuEntry *S::GUI::Menubar::AddEntryInternal(const String &text, const Bitmap &bitmap, PopupMenu *popupMenu, Bool *bVar, Int *iVar, Int iCode) { MenuEntry *newEntry = new MenubarEntry(text, bitmap, popupMenu, bVar, iVar, iCode); if (Add(newEntry) == Success()) { createdEntry.Set(newEntry->GetHandle(), True); if (GetHeight() < newEntry->GetHeight() + 2) SetHeight(newEntry->GetHeight() + 2); if (GetWidth() < newEntry->GetWidth() + 3) SetWidth(newEntry->GetWidth() + 3); return newEntry; } DeleteObject(newEntry); return NIL; } S::Int S::GUI::Menubar::Show() { if (visible) return Success(); #ifdef __APPLE__ if (menubarCocoa != NIL) { visible = True; return menubarCocoa->Show(); } #endif return Menu::Show(); } S::Int S::GUI::Menubar::Hide() { if (!visible) return Success(); #ifdef __APPLE__ if (menubarCocoa != NIL) { visible = False; return menubarCocoa->Hide(); } #endif return Menu::Hide(); } S::Int S::GUI::Menubar::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); #ifdef __APPLE__ if (orientation == OR_FREE) { if (menubarCocoa != NIL) menubarCocoa->Paint(message); return Success(); } #endif Window *window = GetContainerWindow(); Surface *surface = GetDrawSurface(); Rect menubar = Rect(GetRealPosition(), GetRealSize() - Size(1, 1)); #ifdef __WIN32__ static Bool flatStyle = Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2); #else static Bool flatStyle = True; #endif if (orientation == OR_TOP || orientation == OR_BOTTOM) { #ifdef __APPLE__ Int leftWidth = 0; Int rightWidth = 0; for (Int i = 0; i < Length(); i++) { MenuEntry *entry = GetNthEntry(i); if (entry->GetOrientation() == OR_TOP || entry->GetOrientation() == OR_LEFT) leftWidth += entry->GetWidth() + 2; else if (entry->GetOrientation() == OR_BOTTOM || entry->GetOrientation() == OR_RIGHT) rightWidth += entry->GetWidth() + 2; } Int nextXPosLeft = (GetSize().cx - leftWidth - rightWidth + 2) / 2; Int nextXPosRight = nextXPosLeft + leftWidth + rightWidth - 2; #else Int nextXPosLeft = 7 + (window->GetIcon() != NIL ? 17 : 0); Int nextXPosRight = GetSize().cx - 1; if (flatStyle) nextXPosLeft = 1; #endif Int highestEntry = 0; for (Int i = 0; i < Length(); i++) { MenuEntry *entry = GetNthEntry(i); if (entry->GetOrientation() == OR_TOP) entry->SetOrientation(OR_LEFT); if (entry->GetOrientation() == OR_LEFT) { entry->SetPosition(Point(nextXPosLeft, 2)); nextXPosLeft += entry->GetWidth() + 2; if (highestEntry < entry->GetHeight()) highestEntry = entry->GetHeight(); } } for (Int i = Length() - 1; i >= 0; i--) { MenuEntry *entry = GetNthEntry(i); if (entry->GetOrientation() == OR_BOTTOM) entry->SetOrientation(OR_RIGHT); if (entry->GetOrientation() == OR_RIGHT) { entry->SetPosition(Point(nextXPosRight - entry->GetWidth(), 2)); nextXPosRight -= entry->GetWidth() + 2; if (highestEntry < entry->GetHeight()) highestEntry = entry->GetHeight(); } } SetHeight(highestEntry + 2); for (Int i = 0; i < Length(); i++) { MenuEntry *entry = GetNthEntry(i); if (entry->GetText() == NIL && entry->GetBitmap() == NIL) entry->SetHeight(GetHeight() - 3); } } else if (orientation == OR_LEFT || orientation == OR_RIGHT) { Int nextYPos = 1; Int widestEntry = 0; for (Int i = 0; i < Length(); i++) { MenuEntry *entry = GetNthEntry(i); if (entry->GetOrientation() == OR_LEFT) entry->SetOrientation(OR_TOP); if (entry->GetOrientation() == OR_TOP) { entry->SetPosition(Point(1, nextYPos)); nextYPos += entry->GetHeight() + 2; if (widestEntry < entry->GetWidth()) widestEntry = entry->GetWidth(); } } for (Int i = 0; i < Length(); i++) { MenuEntry *entry = GetNthEntry(i); if (entry->GetOrientation() == OR_RIGHT) entry->SetOrientation(OR_BOTTOM); if (entry->GetOrientation() == OR_BOTTOM) { entry->SetPosition(Point(1, nextYPos)); nextYPos += entry->GetHeight() + 2; if (widestEntry < entry->GetWidth()) widestEntry = entry->GetWidth(); } } SetWidth(widestEntry + 3); for (Int i = 0; i < Length(); i++) { MenuEntry *entry = GetNthEntry(i); if (entry->GetText() == NIL && entry->GetBitmap() == NIL) entry->SetWidth(GetWidth() - 3); } } /* Draw handles of non-flat style menubars. */ switch (message) { case SP_PAINT: if (flatStyle) break; if (orientation == OR_TOP || orientation == OR_BOTTOM) { if (orientation == OR_BOTTOM) { menubar.top--; menubar.bottom--; } Point p1 = Point(menubar.left + 1, menubar.top + 2); Point p2 = Point(p1.x, menubar.bottom); if (window->GetIcon() != NIL && orientation == OR_TOP) { p1.x += Math::Round(18 * surface->GetSurfaceDPI() / 96.0) - 1; p2.x += Math::Round(18 * surface->GetSurfaceDPI() / 96.0) - 1; } surface->Bar(p1, p2, OR_VERT); p1.x += 2; p2.x += 2; surface->Bar(p1, p2, OR_VERT); } break; } return Widget::Paint(message); } S::Int S::GUI::Menubar::Process(Int message, Int wParam, Int lParam) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); if (orientation == OR_FREE) return Success(); return Menu::Process(message, wParam, lParam); } S::Void S::GUI::Menubar::OnRegister() { #ifdef __APPLE__ Window *window = GetContainerWindow(); for (Int i = 0; i < window->GetNOfObjects(); i++) { const Widget *widget = window->GetNthObject(i); if (widget->GetObjectType() == classID && widget != this) return; } orientation = OR_FREE; menubarCocoa = new MenubarCocoa(this); Add(menubarCocoa); #endif } S::Void S::GUI::Menubar::OnUnregister() { #ifdef __APPLE__ if (menubarCocoa == NIL) return; Remove(menubarCocoa); DeleteObject(menubarCocoa); #endif } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/menubar_cocoa.mm000066400000000000000000000252571516402577000271100ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include using namespace smooth; using namespace smooth::GUI; const S::Short S::GUI::MenubarCocoa::classID = S::Object::RequestClassID(); class CocoaMenuEntryDelegate; /* CocoaMenuEntry implements basic mapping from * smooth menu entries to Cocoa menu items. */ @interface CocoaMenuEntry : NSMenuItem { @private const MenuEntry *menuEntry; CocoaMenuEntryDelegate *menuEntryDelegate; } - (id) initWithMenuEntry: (const MenuEntry *) iMenuEntry ignoreLastEntry: (BOOL) ignoreLastEntry; - (void) dispose; - (void) checkValue; - (void) onAction; @end /* CocoaMenu implements basic mapping * from smooth menus to Cocoa menus. */ @interface CocoaMenu : NSMenu { @private const Menu *menu; @protected Array menuItems; } - (id) initWithMenu: (const Menu *) iMenu title: (const String &) iTitle ignoreLastEntry: (BOOL) ignoreLastEntry; - (void) dispose; @end /* CocoaMenubar implements specific behaviour only needed * for the menubar such as filling the application menu. */ @interface CocoaMenubar : CocoaMenu { @private const Menubar *menubar; CocoaMenuEntry *aboutItem; CocoaMenuEntry *quitItem; } - (id) initWithMenubar: (const Menubar *) iMenubar; - (void) dispose; @end /* CocoaMenuEntry implements basic mapping from * smooth menu entries to Cocoa menu items. */ class CocoaMenuEntryDelegate { private: CocoaMenuEntry *menuEntry; public: CocoaMenuEntryDelegate(CocoaMenuEntry *iMenuEntry) : menuEntry(iMenuEntry) { CheckBox::internalCheckValues.Connect(&CocoaMenuEntryDelegate::OnCheckValues, this); OptionBox::internalCheckValues.Connect(&CocoaMenuEntryDelegate::OnCheckValues, this); } ~CocoaMenuEntryDelegate() { CheckBox::internalCheckValues.Disconnect(&CocoaMenuEntryDelegate::OnCheckValues, this); OptionBox::internalCheckValues.Disconnect(&CocoaMenuEntryDelegate::OnCheckValues, this); } slots: Void OnCheckValues() { [menuEntry checkValue]; } }; @implementation CocoaMenuEntry - (id) initWithMenuEntry: (const MenuEntry *) iMenuEntry ignoreLastEntry: (BOOL) ignoreLastEntry { [super initWithTitle: [NSString stringWithUTF8String: iMenuEntry->GetText().ConvertTo("UTF-8")] action: @selector(onAction) keyEquivalent: @""]; menuEntry = iMenuEntry; menuEntryDelegate = new CocoaMenuEntryDelegate(self); if (menuEntry->GetPopupMenu() != NIL) { NSMenu *submenu = [[CocoaMenu alloc] initWithMenu: menuEntry->GetPopupMenu() title: menuEntry->GetText() ignoreLastEntry: ignoreLastEntry]; [self setSubmenu: submenu]; [self setAction: nil]; } if (menuEntry->GetShortcut() != NIL) { const Shortcut *shortcut = menuEntry->GetShortcut(); Int key = shortcut->GetKey(); Int flags = shortcut->GetFlags(); String keyString; if (key >= Input::Keyboard::Key0 && key <= Input::Keyboard::Key9) keyString[0] = '0' + key - Input::Keyboard::Key0; else if (key >= Input::Keyboard::KeyA && key <= Input::Keyboard::KeyZ) keyString[0] = 'a' + key - Input::Keyboard::KeyA; else if (key >= Input::Keyboard::KeyF1 && key <= Input::Keyboard::KeyF24) keyString[0] = 0xF704 + key - Input::Keyboard::KeyF1; if (keyString != NIL) { [self setKeyEquivalent: [NSString stringWithUTF8String: keyString.ConvertTo("UTF-8")]]; [self setKeyEquivalentModifierMask: (flags & SC_CTRL ? NSControlKeyMask : 0) | (flags & SC_CMD ? NSCommandKeyMask : 0) | (flags & SC_ALT ? NSAlternateKeyMask : 0) | (flags & SC_SHIFT ? NSShiftKeyMask : 0)]; } } if (!menuEntry->IsActive()) [self setEnabled: NO]; [self checkValue]; [self setTarget: self]; return self; } - (void) dispose { delete menuEntryDelegate; if ([self hasSubmenu]) { if ([[self submenu] respondsToSelector: @selector(dispose)]) [[self submenu] performSelector: @selector(dispose)]; [[self submenu] release]; [self setSubmenu: nil]; } } - (void) checkValue { if (menuEntry->GetCheckVariable() != NIL) { [self setState: *menuEntry->GetCheckVariable()]; } else if (menuEntry->GetOptionVariable() != NIL) { if (*menuEntry->GetOptionVariable() == menuEntry->GetOptionCode()) [self setState: NSOnState]; else [self setState: NSOffState]; } } - (void) onAction { if (menuEntry->GetCheckVariable() != NIL) { *menuEntry->GetCheckVariable() = !*menuEntry->GetCheckVariable(); [self setState: *menuEntry->GetCheckVariable()]; CheckBox::internalCheckValues.Emit(); } else if (menuEntry->GetOptionVariable() != NIL) { *menuEntry->GetOptionVariable() = menuEntry->GetOptionCode(); OptionBox::internalCheckValues.Emit(); } menuEntry->onAction.Emit(); } @end /* CocoaMenu implements basic mapping * from smooth menus to Cocoa menus. */ @implementation CocoaMenu - (id) initWithMenu: (const Menu *) iMenu title: (const String &) iTitle ignoreLastEntry: (BOOL) ignoreLastEntry { [super initWithTitle: [NSString stringWithUTF8String: iTitle.ConvertTo("UTF-8")]]; [super setAutoenablesItems: NO]; menu = iMenu; for (Int i = 0; i < menu->Length(); i++) { const MenuEntry *entry = menu->GetNthEntry(i); if (ignoreLastEntry && ( i == menu->Length() - 1 || (i == menu->Length() - 2 && entry->GetText() == NIL))) break; /* Add menu item. */ NSMenuItem *item = nil; if (entry->GetText() != NIL) item = [[CocoaMenuEntry alloc] initWithMenuEntry: entry ignoreLastEntry: NO]; else item = [[NSMenuItem separatorItem] retain]; menuItems.Add(item); [self addItem: item]; } return self; } - (void) dispose { foreach (NSMenuItem *item, menuItems) { [self removeItem: item]; if ([item respondsToSelector: @selector(dispose)]) [item performSelector: @selector(dispose)]; [item release]; } } @end /* CocoaMenubar implements specific behaviour only needed * for the menubar such as filling the application menu. */ @implementation CocoaMenubar - (id) initWithMenubar: (const Menubar *) iMenubar { [super initWithTitle: @"MainMenu"]; [super setAutoenablesItems: NO]; menubar = iMenubar; /* Build application menu. */ NSMenu *appMenu = [[NSMenu alloc] initWithTitle: @"Apple"]; aboutItem = nil; quitItem = nil; /* Add About... entry. */ if (menubar->Length() >= 1 && menubar->GetNthEntry(menubar->Length() - 1)->GetOrientation() == OR_RIGHT && menubar->GetNthEntry(menubar->Length() - 1)->GetPopupMenu() != NIL) { const Menu *lastMenu = menubar->GetNthEntry(menubar->Length() - 1)->GetPopupMenu(); aboutItem = [[CocoaMenuEntry alloc] initWithMenuEntry: lastMenu->GetNthEntry(lastMenu->Length() - 1) ignoreLastEntry: NO]; [appMenu addItem: aboutItem]; [appMenu addItem: [NSMenuItem separatorItem]]; } /* Add Hide... entries. */ NSMenuItem *hideItem = [appMenu addItemWithTitle: NSLocalizedString(@"Hide", nil) action: @selector(hide:) keyEquivalent: @"h"]; [hideItem setTarget: NSApp]; NSMenuItem *hideOthersItem = [appMenu addItemWithTitle: NSLocalizedString(@"Hide Others", nil) action: @selector(hideOtherApplications:) keyEquivalent: @"h"]; [hideOthersItem setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask]; [hideOthersItem setTarget: NSApp]; /* Add Quit entry. */ if (menubar->Length() >= 1 && menubar->GetNthEntry(0)->GetPopupMenu() != NIL) { const Menu *firstMenu = menubar->GetNthEntry(0)->GetPopupMenu(); quitItem = [[CocoaMenuEntry alloc] initWithMenuEntry: firstMenu->GetNthEntry(firstMenu->Length() - 1) ignoreLastEntry: NO]; [appMenu addItem: [NSMenuItem separatorItem]]; [appMenu addItem: quitItem]; } NSMenuItem *appMenuItem = [[NSMenuItem alloc] initWithTitle: @"Apple" action: nil keyEquivalent: @""]; [appMenuItem setSubmenu: appMenu]; menuItems.Add(appMenuItem); [self addItem: appMenuItem]; [NSApp performSelector: @selector(setAppleMenu:) withObject: appMenu]; /* Add other menus. */ for (Int i = 0; i < menubar->Length(); i++) { const MenuEntry *entry = menubar->GetNthEntry(i); if (entry->GetText() == NIL) continue; /* Add menu item. */ NSMenuItem *item = [[CocoaMenuEntry alloc] initWithMenuEntry: entry ignoreLastEntry: (i == 0 && quitItem != nil) || (i == menubar->Length() - 1 && aboutItem != nil)]; menuItems.Add(item); [self addItem: item]; } [NSApp setMainMenu: self]; return self; } - (void) dispose { [super dispose]; [aboutItem dispose]; [aboutItem release]; [quitItem dispose]; [quitItem release]; } @end S::GUI::MenubarCocoa::MenubarCocoa(Menubar *iMenubar) : Widget(Point(), Size()) { type = classID; orientation = OR_FREE; menubar = iMenubar; menubarCocoa = NIL; CheckBox::internalCheckValues.Connect(&MenubarCocoa::UpdateCocoaMenubar, this); OptionBox::internalCheckValues.Connect(&MenubarCocoa::UpdateCocoaMenubar, this); } S::GUI::MenubarCocoa::~MenubarCocoa() { CheckBox::internalCheckValues.Disconnect(&MenubarCocoa::UpdateCocoaMenubar, this); OptionBox::internalCheckValues.Disconnect(&MenubarCocoa::UpdateCocoaMenubar, this); if (menubarCocoa != NIL) { [(CocoaMenubar *) menubarCocoa dispose]; [(CocoaMenubar *) menubarCocoa release]; } } S::Int S::GUI::MenubarCocoa::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Window *window = GetContainerWindow(); if (GetSize() == Size()) SetSize(window->GetSize()); if (GetSize() == window->GetSize()) UpdateCocoaMenubar(); SetVisibleDirect(False); SetSize(window->GetSize()); SetVisibleDirect(True); return Success(); } S::Void S::GUI::MenubarCocoa::UpdateCocoaMenubar() { if (menubarCocoa != NIL) { [(CocoaMenubar *) menubarCocoa dispose]; [(CocoaMenubar *) menubarCocoa release]; } menubarCocoa = [[CocoaMenubar alloc] initWithMenubar: menubar]; } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/menubarentry.cpp000077500000000000000000000241721516402577000271750ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include const S::Short S::GUI::MenubarEntry::classID = S::Object::RequestClassID(); S::GUI::MenubarEntry::MenubarEntry(const String &iText, const Bitmap &iBitmap, PopupMenu *iPopup, Bool *ibVar, Int *iiVar, Int iiCode) : MenuEntry(iText, iBitmap, iPopup, ibVar, iiVar, iiCode) { type = classID; if (text == NIL && bitmap == NIL) SetSize(Size(4, 15)); else if (text != NIL && bitmap == NIL) SetSize(Size(unscaledTextSize.cx + 7, 16)); else if (text == NIL && bitmap != NIL) SetSize(bitmap.GetSize() + Size(4 + (popup != NIL ? 12 : 0), 4)); hotspot = NIL; actionHotspot = NIL; if (text != NIL || bitmap != NIL) { hotspot = new HotspotSimpleButton(Point(), GetSize()); hotspot->onMouseOver.Connect(&MenubarEntry::OnMouseOver, this); hotspot->onLeftButtonDown.Connect(&MenubarEntry::OpenPopupMenu, this); actionHotspot = new Hotspot(Point(), GetSize() - Size((text == NIL && bitmap != NIL && popup != NIL ? 12 : 0), 0)); actionHotspot->onLeftButtonClick.Connect(&onAction); if (text == NIL && bitmap != NIL && popup != NIL) actionHotspot->onLeftButtonDown.Connect(&MenubarEntry::ClosePopupMenu, this); Add(hotspot); Add(actionHotspot); } popupMenuClosed = 0; onChangeSize.Connect(&MenubarEntry::OnChangeSize, this); } S::GUI::MenubarEntry::~MenubarEntry() { if (hotspot != NIL) DeleteObject(hotspot); if (actionHotspot != NIL) DeleteObject(actionHotspot); } S::Int S::GUI::MenubarEntry::Show() { if (visible) return Success(); #ifdef __APPLE__ if (IsRegistered() && container->GetOrientation() == OR_FREE) { visible = True; onShow.Emit(); return container->Paint(SP_UPDATE); } #endif return MenuEntry::Show(); } S::Int S::GUI::MenubarEntry::Hide() { if (!visible) return Success(); #ifdef __APPLE__ if (IsRegistered() && container->GetOrientation() == OR_FREE) { visible = False; onHide.Emit(); return container->Paint(SP_UPDATE); } #endif return MenuEntry::Hide(); } S::Int S::GUI::MenubarEntry::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); #ifdef __APPLE__ if (container->GetOrientation() == OR_FREE) return container->Paint(SP_UPDATE); #endif Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Rect bmpRect = Rect(realPos + Point(2, 2) * surface->GetSurfaceDPI() / 96.0, (GetSize() - Size(4 + (popup != NIL ? 12 : 0), 4)) * surface->GetSurfaceDPI() / 96.0); switch (message) { case SP_PAINT: surface->StartPaint(Rect(realPos, realSize)); if (text == NIL && bitmap == NIL) { if (orientation == OR_LEFT || orientation == OR_RIGHT) { SetWidth(4); Point p1 = Point(realPos.x, realPos.y); Point p2 = Point(p1.x, p1.y + realSize.cy); surface->Bar(p1, p2, OR_VERT); p1.x += 2; p2.x += 2; surface->Bar(p1, p2, OR_VERT); } else if (orientation == OR_TOP || orientation == OR_BOTTOM) { SetHeight(4); Point p1 = Point(realPos.x, realPos.y); Point p2 = Point(p1.x + realSize.cx, p1.y); surface->Bar(p1, p2, OR_HORZ); p1.y += 2; p2.y += 2; surface->Bar(p1, p2, OR_HORZ); } } else if (text != NIL && bitmap == NIL) { Rect textRect = Rect(realPos + Point(1, Math::Ceil(Float(realSize.cy - scaledTextSize.cy) / 2) - 1) + Point(2, 0) * surface->GetSurfaceDPI() / 96.0, realSize - Size(2, 2) - Size(2, 0) * surface->GetSurfaceDPI() / 96.0); Font nFont = font; if (!IsActive()) nFont.SetColor(Setup::InactiveTextColor); surface->Box(textRect, GetBackgroundColor(), Rect::Filled); surface->SetText(text, textRect, nFont); } else if (text == NIL && bitmap != NIL) { surface->Box(bmpRect, Setup::BackgroundColor, Rect::Filled); if (flags & MB_COLOR) surface->BlitFromBitmap(bitmap, Rect(Point(0, 0), bitmap.GetSize()), bmpRect); else surface->BlitFromBitmap(graymap, Rect(Point(0, 0), graymap.GetSize()), bmpRect); if (popup != NIL) { Int height = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); Point lineStart = realPos + Point(realSize.cx - height * 2 - 2 * surface->GetSurfaceDPI() / 96.0 - (IsRightToLeft() ? 0 : 1), (realSize.cy - height) / 2 + 1); Point lineEnd = lineStart + Point(height * 2 - 1, 0); for (Int i = 0; i < height; i++) { surface->Line(lineStart, lineEnd, Setup::TextColor); lineStart += Point(1, 1); lineEnd += Point(-1, 1); } } } surface->EndPaint(); break; case SP_MOUSEIN: case SP_MOUSEUP: if (focussed && popup != NIL) if (popup->GetContainer() == this) break; if (bitmap != NIL) { surface->StartPaint(Rect(realPos, realSize)); surface->Box(bmpRect, Setup::BackgroundColor, Rect::Filled); surface->BlitFromBitmap(bitmap, Rect(Point(0, 0), bitmap.GetSize()), bmpRect); if (onAction.GetNOfConnectedSlots() > 0 && popup != NIL) { Point p1 = Point(realPos.x + realSize.cx - 11 * surface->GetSurfaceDPI() / 96.0 - 2, realPos.y + 1); Point p2 = Point(realPos.x + realSize.cx - 11 * surface->GetSurfaceDPI() / 96.0 - 2, realPos.y + realSize.cy - 2); surface->Bar(p1, p2, OR_VERT); } surface->EndPaint(); } break; case SP_MOUSEOUT: if (focussed && popup != NIL) if (popup->GetContainer() == this) break; if (bitmap != NIL) { surface->StartPaint(Rect(realPos, realSize)); surface->Box(bmpRect, Setup::BackgroundColor, Rect::Filled); if (flags & MB_COLOR) surface->BlitFromBitmap(bitmap, Rect(Point(0, 0), bitmap.GetSize()), bmpRect); else surface->BlitFromBitmap(graymap, Rect(Point(0, 0), graymap.GetSize()), bmpRect); if (onAction.GetNOfConnectedSlots() > 0 && popup != NIL) { Point p1 = Point(realPos.x + realSize.cx - 11 * surface->GetSurfaceDPI() / 96.0 - 2 + (IsRightToLeft() ? 1 : 0), realPos.y + 1); Point p2 = Point(realPos.x + realSize.cx - 11 * surface->GetSurfaceDPI() / 96.0 - 2 + (IsRightToLeft() ? 1 : 0), realPos.y + realSize.cy - 1); surface->Line(p1, p2, Setup::BackgroundColor); p1.x++; p2.x++; surface->Line(p1, p2, Setup::BackgroundColor); } surface->EndPaint(); } break; } return Success(); } S::Void S::GUI::MenubarEntry::OnMouseOver() { if (Binary::IsFlagSet(container->GetFlags(), MB_POPUPOPEN) && text != NIL && bitmap == NIL) { hotspot->Paint(SP_MOUSEDOWN); OpenPopupMenu(); } } S::Void S::GUI::MenubarEntry::OnChangeSize(const Size &nSize) { if (hotspot == NIL || actionHotspot == NIL) return; hotspot->SetSize(nSize); actionHotspot->SetSize(nSize - Size((text == NIL && bitmap != NIL && popup != NIL ? 12 : 0), 0)); } S::Void S::GUI::MenubarEntry::OpenPopupMenu() { if (popup == NIL) return; if (S::System::System::Clock() - popupMenuClosed < 100) { hotspot->Paint(SP_MOUSEUP); return; } Window *window = container->GetContainerWindow(); Surface *surface = GetDrawSurface(); Float scaleFactor = surface->GetSurfaceDPI() / 96.0; Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Rect popupFrame = Rect(realPos + Point(realSize.cx - 11 * scaleFactor, 0), Size(11 * scaleFactor, realSize.cy)); if (onAction.GetNOfConnectedSlots() == 0 || window->IsMouseOn(popupFrame)) { hotspot->Deactivate(); Rect monitor = System::Screen::GetActiveScreenWorkArea(); popup->CalculateSize(); Point popupPos = realPos + Point(orientation == OR_LEFT ? -1 : realSize.cx + 1 - popup->GetWidth() * scaleFactor, realSize.cy + 1); Size popupSize = popup->GetSize(); if (orientation == OR_LEFT) { if (!IsRightToLeft()) { if (window->GetX() + popupPos.x + Math::Round(popupSize.cx * scaleFactor) >= monitor.right) popupPos.x = realPos.x + realSize.cx + 1 - Math::Round(popupSize.cx * scaleFactor); } else { if (window->GetX() + (window->GetWidth() - popupPos.x) - Math::Round(popupSize.cx * scaleFactor) < monitor.left) popupPos.x = realPos.x + realSize.cx + 1 - Math::Round(popupSize.cx * scaleFactor); } } else { if (!IsRightToLeft()) { if (window->GetX() + popupPos.x < monitor.left) popupPos.x = realPos.x - 1; } else { if (window->GetX() + (window->GetWidth() - popupPos.x) >= monitor.right) popupPos.x = realPos.x - 1; } } if (window->GetY() + popupPos.y + Math::Round(popupSize.cy * scaleFactor) >= monitor.bottom) popupPos.y = realPos.y - Math::Round(popupSize.cy * scaleFactor) - 1; popup->SetPosition(popupPos); popup->internalRequestClose.Connect(&MenubarEntry::ClosePopupMenu, this); Add(popup); container->SetFlags(container->GetFlags() | MB_POPUPOPEN); } } S::Void S::GUI::MenubarEntry::ClosePopupMenu() { if (popup == NIL || popup->GetContainer() != this) return; if (IsRegistered()) container->SetFlags(container->GetFlags() & ~MB_POPUPOPEN); Remove(popup); popup->internalRequestClose.Disconnect(&MenubarEntry::ClosePopupMenu, this); if (IsRegistered()) { Window *window = container->GetContainerWindow(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->StartPaint(frame); if (!window->IsMouseOn(frame)) Paint(SP_MOUSEOUT); hotspot->Activate(); surface->EndPaint(); } popupMenuClosed = S::System::System::Clock(); } S::Bool S::GUI::MenubarEntry::IsTypeCompatible(Short compType) const { if (compType == MenuEntry::classID) return True; else return MenuEntry::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/menuentry.cpp000077500000000000000000000042161516402577000265050ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include const S::Short S::GUI::MenuEntry::classID = S::Object::RequestClassID(); S::GUI::MenuEntry::MenuEntry(const String &iText, const Bitmap &iBitmap, PopupMenu *iPopup, Bool *ibVar, Int *iiVar, Int iiCode) { type = classID; popup = NIL; bVar = ibVar; iVar = iiVar; iCode = iiCode; orientation = OR_LEFT; shortcut = NIL; SetText(iText); SetBitmap(iBitmap); SetPopupMenu(iPopup); } S::GUI::MenuEntry::~MenuEntry() { if (shortcut != NIL) DeleteObject(shortcut); if (popup != NIL) popup->onEnqueueForDeletion.Disconnect(&MenuEntry::InternalOnDeletePopup, this); } S::Void S::GUI::MenuEntry::InternalOnDeletePopup() { popup = NIL; } S::Int S::GUI::MenuEntry::SetShortcut(Int scFlags, Int scKey, Window *window) { shortcut = new Shortcut(scFlags, scKey, this); shortcut->onKeyDown.Connect(&onAction); window->Add(shortcut); return Success(); } S::Int S::GUI::MenuEntry::SetPopupMenu(PopupMenu *nPopup) { if (popup != NIL) popup->onEnqueueForDeletion.Disconnect(&MenuEntry::InternalOnDeletePopup, this); popup = nPopup; if (popup != NIL) popup->onEnqueueForDeletion.Connect(&MenuEntry::InternalOnDeletePopup, this); return Success(); } S::Int S::GUI::MenuEntry::SetBitmap(const Bitmap &newBitmap) { bitmap = newBitmap; graymap = newBitmap; if (bitmap == NIL) return Success(); graymap.GrayscaleBitmap(); return Success(); } S::Bool S::GUI::MenuEntry::IsTypeCompatible(Short compType) const { if (compType == Entry::classID) return True; else return Entry::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/micromenu.cpp000077500000000000000000000125711516402577000264600ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include const S::Short S::GUI::MicroMenu::classID = S::Object::RequestClassID(); S::GUI::MicroMenu::MicroMenu(const Point &iPos, const Size &iSize, Int sType) { type = classID; subtype = sType; SetMetrics(iPos, iSize); if (GetWidth() == 0) SetWidth(subtype == OR_VERT ? 13 : 7); if (GetHeight() == 0) SetHeight(subtype == OR_VERT ? 7 : 13); onOpenPopupMenu.SetParentObject(this); onClosePopupMenu.SetParentObject(this); hotspot = new HotspotSimpleButton(Point(), GetSize()); hotspot->onLeftButtonDown.Connect(&MicroMenu::OpenPopupMenu, this); Add(hotspot); popup = new PopupMenu(); } S::GUI::MicroMenu::~MicroMenu() { DeleteObject(popup); DeleteObject(hotspot); } S::GUI::MenuEntry *S::GUI::MicroMenu::AddEntryInternal(const String &text, const Bitmap &bitmap, PopupMenu *popupMenu, Bool *bVar, Int *iVar, Int iCode) { if (bVar != NIL) return popup->AddEntry(text, bVar); else if (iVar != NIL) return popup->AddEntry(text, iVar, iCode); return popup->AddEntry(text, bitmap, popupMenu); } S::Int S::GUI::MicroMenu::Remove(Widget *widget) { if (widget->GetObjectType() == Entry::classID) return popup->Remove(widget); return Menu::Remove(widget); } S::Int S::GUI::MicroMenu::RemoveAllEntries() { return popup->RemoveAllEntries(); } S::GUI::Rect S::GUI::MicroMenu::GetVisibleArea() const { /* MicroMenus are usually placed outside of their containers, * so let's ignore the containers visible area. */ return Rect(GetRealPosition(), GetRealSize()); } S::Int S::GUI::MicroMenu::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); switch (message) { case SP_PAINT: surface->StartPaint(frame); if (IsBackgroundColorSet()) surface->Box(frame, GetBackgroundColor(), Rect::Filled); surface->Frame(frame, FRAME_UP); if (subtype == OR_HORZ) { Int size = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); for (Int i = 0; i < size; i++) { Point lineStart = Point(frame.left + (frame.GetWidth() - size) / 2 + i, frame.top + frame.GetHeight() / 2 - size + 1 + i); Point lineEnd = lineStart + Point(0, 2 * (size - i) - 1); if (IsActive()) surface->Line(lineStart, lineEnd, Setup::TextColor); else surface->Line(lineStart, lineEnd, Setup::InactiveTextColor); } } else if (subtype == OR_VERT) { Int size = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); for (Int i = 0; i < size; i++) { Point lineStart = Point(frame.left + frame.GetWidth() / 2 - size + 1 + (IsRightToLeft() ? 1 : 0) + i, frame.top + (frame.GetHeight() - size) / 2 + i); Point lineEnd = lineStart + Point(2 * (size - i) - 1, 0); if (IsActive()) surface->Line(lineStart, lineEnd, Setup::TextColor); else surface->Line(lineStart, lineEnd, Setup::InactiveTextColor); } } surface->EndPaint(); break; case SP_MOUSEOUT: if (hotspot->IsActive()) surface->Frame(frame, FRAME_UP); break; } return Success(); } S::Void S::GUI::MicroMenu::OpenPopupMenu() { if (popup == NIL) return; Widget *window = container->GetContainerWindow(); Surface *surface = GetDrawSurface(); if (window == NIL) return; hotspot->Deactivate(); Rect monitor = System::Screen::GetActiveScreenWorkArea(); Float scaleFactor = surface->GetSurfaceDPI() / 96.0; popup->CalculateSize(); Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Point popupPos = realPos + Point(subtype == OR_HORZ ? realSize.cx : 0, subtype == OR_VERT ? realSize.cy : 0); Size popupSize = popup->GetSize(); if (!IsRightToLeft()) { if (window->GetX() + popupPos.x + Math::Round(popupSize.cx * scaleFactor) >= monitor.right) popupPos.x = realPos.x - Math::Round(popupSize.cx * scaleFactor) + (subtype == OR_VERT ? realSize.cx : 0); } else { if (window->GetX() + (window->GetWidth() - popupPos.x) - Math::Round(popupSize.cx * scaleFactor) < monitor.left) popupPos.x = realPos.x - Math::Round(popupSize.cx * scaleFactor) + (subtype == OR_VERT ? realSize.cx : 0); } if (window->GetY() + popupPos.y + Math::Round(popupSize.cy * scaleFactor) >= monitor.bottom) popupPos.y = realPos.y - Math::Round(popupSize.cy * scaleFactor) + (subtype == OR_HORZ ? GetHeight() : 0); popup->SetPosition(popupPos); popup->internalRequestClose.Connect(&MicroMenu::ClosePopupMenu, this); onOpenPopupMenu.Emit(); Add(popup); } S::Void S::GUI::MicroMenu::ClosePopupMenu() { if (popup == NIL || popup->GetContainer() != this) return; Remove(popup); onClosePopupMenu.Emit(); popup->internalRequestClose.Disconnect(&MicroMenu::ClosePopupMenu, this); hotspot->Activate(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/popupmenu.cpp000077500000000000000000000122211516402577000265020ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include const S::Short S::GUI::PopupMenu::classID = S::Object::RequestClassID(); S::Signal1 S::GUI::PopupMenu::internalOnOpenPopupMenu; S::GUI::PopupMenu::PopupMenu() { type = classID; orientation = OR_FREE; closedByClick = False; toolWindow = NIL; internalRequestClose.SetParentObject(this); internalOnOpenPopupMenu.Connect(&PopupMenu::OnOpenPopupMenu, this); } S::GUI::PopupMenu::~PopupMenu() { internalOnOpenPopupMenu.Disconnect(&PopupMenu::OnOpenPopupMenu, this); } S::GUI::MenuEntry *S::GUI::PopupMenu::AddEntryInternal(const String &text, const Bitmap &bitmap, PopupMenu *popupMenu, Bool *bVar, Int *iVar, Int iCode) { PopupMenuEntry *newEntry = NIL; if (bVar != NIL) newEntry = new PopupMenuEntryCheck(text, bVar); else if (iVar != NIL) newEntry = new PopupMenuEntryOption(text, iVar, iCode); else newEntry = new PopupMenuEntry(text, bitmap, popupMenu); newEntry->SetOwner(this); if (Add(newEntry) == Success()) { createdEntry.Set(newEntry->GetHandle(), True); return newEntry; } DeleteObject(newEntry); return NIL; } S::Int S::GUI::PopupMenu::Show() { if (IsVisible()) return Success(); visible = True; if (!IsRegistered()) return Success(); SetFlags(GetFlags() & ~MB_POPUPOPEN); closedByClick = False; Window *window = container->GetContainerWindow(); /* Create tool window, add entries and display it. */ toolWindow = new ToolWindow(GetPosition(), GetSize()); toolWindow->onPaint.Connect(&PopupMenu::OnToolWindowPaint, this); toolWindow->onLoseFocus.Connect(&internalRequestClose); window->onChangePosition.Connect(&internalRequestClose); window->onChangeSize.Connect(&internalRequestClose); for (Int i = 0; i < Length(); i++) { MenuEntry *entry = GetNthEntry(i); if (entry->GetObjectType() != PopupMenuEntry::classID) continue; entry->SetRegisteredFlag(False); toolWindow->Add(entry); } Add(toolWindow); internalOnOpenPopupMenu.Emit(GetHandle()); toolWindow->Show(); /* Notify subscribers of popup open. */ onShow.Emit(); return Success(); } S::Int S::GUI::PopupMenu::Hide() { if (!visible) return Success(); visible = False; if (!IsRegistered()) return Success(); Window *window = container->GetContainerWindow(); /* Close tool window, remove entries and delete it. */ toolWindow->Close(); window->onChangePosition.Disconnect(&internalRequestClose); window->onChangeSize.Disconnect(&internalRequestClose); for (Int i = 0; i < Length(); i++) { MenuEntry *entry = GetNthEntry(i); if (entry->GetObjectType() != PopupMenuEntry::classID) continue; toolWindow->Remove(entry); entry->SetRegisteredFlag(True); entry->SetContainer(this); } DeleteObject(toolWindow); toolWindow = NIL; /* Notify subscribers of popup close. */ onHide.Emit(); return Success(); } S::Void S::GUI::PopupMenu::CalculateSize() { SetSize(Size(50, 5)); Int nextYPos = 3; Int maxShortcutTextSize = 0; for (Int i = 0; i < Length(); i++) { PopupMenuEntry *entry = (PopupMenuEntry *) GetNthEntry(i); if (entry->GetObjectType() != PopupMenuEntry::classID) continue; maxShortcutTextSize = Math::Max(maxShortcutTextSize, entry->GetShortcutTextSize()); } for (Int i = 0; i < Length(); i++) { PopupMenuEntry *entry = (PopupMenuEntry *) GetNthEntry(i); if (entry->GetObjectType() != PopupMenuEntry::classID) continue; SetWidth(Math::Max(GetWidth(), 6 + entry->GetMinimumSize().cx - (entry->GetShortcutTextSize() > 0 ? entry->GetShortcutTextSize() - maxShortcutTextSize : 0))); SetHeight(GetHeight() + 5 + (entry->GetText() != NIL ? 11 : 0)); entry->SetPosition(Point(3, nextYPos)); nextYPos += entry->GetHeight() + 1; } for (Int i = 0; i < Length(); i++) { PopupMenuEntry *entry = (PopupMenuEntry *) GetNthEntry(i); if (entry->GetObjectType() != PopupMenuEntry::classID) continue; entry->SetWidth(GetWidth() - 6); entry->SetShortcutOffset(maxShortcutTextSize + 21); } } S::Void S::GUI::PopupMenu::OnOpenPopupMenu(Int handle) { if (GetFlags() & MB_POPUPOPEN) return; if (handle != GetHandle()) internalRequestClose.Emit(); } S::Void S::GUI::PopupMenu::OnToolWindowPaint() { if (toolWindow == NIL) return; Surface *surface = toolWindow->GetDrawSurface(); Rect frame = Rect(Point(0, 0), GetRealSize()); surface->Frame(frame, FRAME_UP); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/popupmenuentry.cpp000077500000000000000000000226661516402577000276020ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2023 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include const S::Short S::GUI::PopupMenuEntry::classID = S::Object::RequestClassID(); S::GUI::PopupMenuEntry::PopupMenuEntry(const String &iText, const Bitmap &iBitmap, PopupMenu *iPopup) : MenuEntry(iText, iBitmap, iPopup) { type = classID; orientation = OR_UPPERLEFT; hotspot = NIL; owner = NIL; timer = NIL; popupMenuClosed = 0; shortcutOffset = 0; SetSize(GetMinimumSize()); if (text != NIL) { hotspot = new Hotspot(Point(), GetSize()); hotspot->onMouseOver.Connect(&PopupMenuEntry::OnMouseOver, this); hotspot->onMouseOut.Connect(&PopupMenuEntry::OnMouseOut, this); hotspot->onLeftButtonDown.Connect(&PopupMenuEntry::OpenPopupMenu, this); hotspot->onLeftButtonUp.Connect(&PopupMenuEntry::OnClickEntry, this); Add(hotspot); onChangeSize.Connect(&PopupMenuEntry::OnChangeSize, this); } } S::GUI::PopupMenuEntry::~PopupMenuEntry() { if (hotspot != NIL) DeleteObject(hotspot); if (timer != NIL) { DeleteObject(timer); timer = NIL; } } S::Int S::GUI::PopupMenuEntry::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Rect bmpRect = Rect(GetRealPosition() + Point(2, 2) * surface->GetSurfaceDPI() / 96.0 - Point(0, 1), Size(12, 12) * surface->GetSurfaceDPI() / 96.0); surface->StartPaint(frame); switch (message) { case SP_PAINT: case SP_MOUSEOUT: if (text == NIL && bitmap == NIL) { Point p1 = Point(frame.left - 1, frame.top + 1); Point p2 = Point(frame.right + 1, frame.top + 1); surface->Bar(p1, p2, OR_HORZ); } else if (text != NIL || bitmap != NIL) { Rect textRect = frame + Point(18 * surface->GetSurfaceDPI() / 96.0, Math::Ceil(Float(frame.GetHeight() - scaledTextSize.cy) / 2) - 2) - Size(4 + 18 * surface->GetSurfaceDPI() / 96.0, 0); Font nFont = font; if (!IsActive()) nFont.SetColor(Setup::InactiveTextColor); surface->Box(frame, Setup::BackgroundColor, Rect::Filled); surface->SetText(text, textRect, nFont); if (bitmap != NIL && bVar == NIL && iVar == NIL) { if (IsActive()) surface->BlitFromBitmap(bitmap, Rect(Point(0, 0), bitmap.GetSize()), bmpRect); else surface->BlitFromBitmap(graymap, Rect(Point(0, 0), graymap.GetSize()), bmpRect); } if (shortcut != NIL) { textRect.left = textRect.right - Math::Round(shortcutOffset * surface->GetSurfaceDPI() / 96.0); surface->SetText(shortcut->ToString(), textRect, nFont); } if (popup != NIL) { Int size = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); Point lineStart = Point(frame.right - 4 - size, frame.top + 1 + Math::Round(4 * surface->GetSurfaceDPI() / 96.0)); Point lineEnd = Point(frame.right - 4 - size, frame.top + 1 + Math::Round(4 * surface->GetSurfaceDPI() / 96.0) + size * 2 - 1); for (Int i = 0; i < size; i++) surface->Line(lineStart + Point(i, i), lineEnd + Point(i, -i), Setup::TextColor); } } break; case SP_MOUSEIN: if (text != NIL || bitmap != NIL) { Rect textRect = frame + Point(18 * surface->GetSurfaceDPI() / 96.0, Math::Ceil(Float(frame.GetHeight() - scaledTextSize.cy) / 2) - 2) - Size(4 + 18 * surface->GetSurfaceDPI() / 96.0, 0); Font nFont = font; nFont.SetColor(Setup::GradientTextColor); surface->Gradient(frame, Setup::GradientStartColor, Setup::GradientEndColor, OR_HORZ); surface->SetText(text, textRect, nFont); if (bitmap != NIL && bVar == NIL && iVar == NIL) { surface->BlitFromBitmap(bitmap, Rect(Point(0, 0), bitmap.GetSize()), bmpRect); } if (shortcut != NIL) { textRect.left = textRect.right - Math::Round(shortcutOffset * surface->GetSurfaceDPI() / 96.0); surface->SetText(shortcut->ToString(), textRect, nFont); } if (popup != NIL) { Int size = Math::Round(3 * surface->GetSurfaceDPI() / 96.0); Point lineStart = Point(frame.right - 4 - size, frame.top + 1 + Math::Round(4 * surface->GetSurfaceDPI() / 96.0)); Point lineEnd = Point(frame.right - 4 - size, frame.top + 1 + Math::Round(4 * surface->GetSurfaceDPI() / 96.0) + size * 2 - 1); for (Int i = 0; i < size; i++) surface->Line(lineStart + Point(i, i), lineEnd + Point(i, -i), Setup::GradientTextColor); } } break; } surface->EndPaint(); return Success(); } S::Int S::GUI::PopupMenuEntry::Show() { visible = True; if (hotspot != NIL) hotspot->Show(); return Success(); } S::Int S::GUI::PopupMenuEntry::Hide() { if (popup != NIL) { if (popup->GetContainer() == this) ClosePopupMenu(); } visible = False; if (hotspot != NIL) hotspot->Hide(); return Success(); } S::GUI::Size S::GUI::PopupMenuEntry::GetMinimumSize() const { if (text != NIL && shortcut == NIL) return Size(unscaledTextSize.cx + 44, 15); if (text != NIL && shortcut != NIL) return Size(unscaledTextSize.cx + font.GetUnscaledTextSizeX(shortcut->ToString()) + 59, 15); return Size(15, 4); } S::Int S::GUI::PopupMenuEntry::GetShortcutTextSize() const { if (shortcut == NIL) return 0; return font.GetUnscaledTextSizeX(shortcut->ToString()); } S::Void S::GUI::PopupMenuEntry::SetShortcutOffset(Int nShortcutOffset) { shortcutOffset = nShortcutOffset; } S::Void S::GUI::PopupMenuEntry::OnMouseOver() { if (popup == NIL || IsMouseOver()) return; if (Binary::IsFlagSet(owner->GetFlags(), MB_POPUPOPEN)) { container->GetContainerWindow()->Raise(); OpenPopupMenu(); } else { if (timer != NIL) DeleteObject(timer); timer = new System::Timer(); timer->onInterval.Connect(&PopupMenuEntry::OpenPopupMenu, this); timer->Start(500); } } S::Void S::GUI::PopupMenuEntry::OnMouseOut() { if (timer != NIL) { DeleteObject(timer); timer = NIL; } } S::Void S::GUI::PopupMenuEntry::OnClickEntry() { if (popup != NIL) return; EnterProtectedRegion(); owner->SetClosedByClick(True); owner->internalRequestClose.Emit(); onAction.Emit(); LeaveProtectedRegion(); } S::Void S::GUI::PopupMenuEntry::OnChangeSize(const Size &nSize) { hotspot->SetSize(nSize); } S::Void S::GUI::PopupMenuEntry::OpenPopupMenu() { if (popup == NIL) return; if (S::System::System::Clock() - popupMenuClosed < 100) return; Widget *window = container->GetContainerWindow(); Surface *surface = GetDrawSurface(); if (window == NIL) return; if (timer != NIL) { DeleteObject(timer); timer = NIL; } hotspot->Deactivate(); Rect monitor = System::Screen::GetActiveScreenWorkArea(); Float scaleFactor = surface->GetSurfaceDPI() / 96.0; popup->CalculateSize(); Point realPos = GetRealPosition(); Size realSize = GetRealSize(); Point popupPos = realPos + Point(realSize.cx, Math::Round(-3 * scaleFactor)); Size popupSize = popup->GetSize(); if (!IsRightToLeft()) { if (window->GetX() + popupPos.x + Math::Round(popupSize.cx * scaleFactor) >= monitor.right) popupPos.x = realPos.x - Math::Round(popupSize.cx * scaleFactor); } else { if (window->GetX() + (window->GetWidth() - popupPos.x) - Math::Round(popupSize.cx * scaleFactor) < monitor.left) popupPos.x = realPos.x - Math::Round(popupSize.cx * scaleFactor); } if (window->GetY() + popupPos.y + Math::Round(popupSize.cy * scaleFactor) >= monitor.bottom) popupPos.y = realPos.y - Math::Round(popupSize.cy * scaleFactor) + realSize.cy + Math::Round(3 * scaleFactor); popup->SetPosition(popupPos); popup->internalRequestClose.Connect(&PopupMenuEntry::ClosePopupMenu, this); owner->SetFlags(owner->GetFlags() | MB_POPUPOPEN); Add(popup); /* Set the MB_POPUPOPEN flag again as it may have been unset by a * closing sibling popup during PopupMenu::Show in the above Add call. */ owner->SetFlags(owner->GetFlags() | MB_POPUPOPEN); } S::Void S::GUI::PopupMenuEntry::ClosePopupMenu() { if (popup == NIL || popup->GetContainer() != this) return; if (IsRegistered()) owner->SetFlags(owner->GetFlags() & ~MB_POPUPOPEN); popup->internalRequestClose.Disconnect(&PopupMenuEntry::ClosePopupMenu, this); Remove(popup); hotspot->Activate(); if (IsRegistered()) { if (popup->IsClosedByClick()) { owner->SetClosedByClick(True); owner->internalRequestClose.Emit(); } else { if (!container->GetContainerWindow()->IsMouseOn(Rect(Point(), container->GetRealSize()))) owner->internalRequestClose.Emit(); else container->GetContainerWindow()->Raise(); } } popupMenuClosed = S::System::System::Clock(); } S::Bool S::GUI::PopupMenuEntry::IsTypeCompatible(Short compType) const { if (compType == MenuEntry::classID) return True; else return MenuEntry::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/popupmenuentrycheck.cpp000077500000000000000000000060401516402577000305640ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::PopupMenuEntryCheck::classID = S::Object::RequestClassID(); S::GUI::PopupMenuEntryCheck::PopupMenuEntryCheck(const String &iText, Bool *ibVar) : PopupMenuEntry(iText) { type = classID; bVar = ibVar; } S::GUI::PopupMenuEntryCheck::~PopupMenuEntryCheck() { } S::Int S::GUI::PopupMenuEntryCheck::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->StartPaint(frame); PopupMenuEntry::Paint(message); switch (message) { case SP_PAINT: case SP_MOUSEIN: case SP_MOUSEOUT: if (*bVar == True) { Float scaleFactor = surface->GetSurfaceDPI() / 96.0; for (Int i = 0; i < 2; i++) { Color color = (IsActive() ? Setup::TextColor : Setup::InactiveTextColor); if (message == SP_MOUSEIN) color = Setup::GradientTextColor; if (i == 0) color = Color(color.GetRed() + (255 - color.GetRed()) * 0.6, color.GetGreen() + (255 - color.GetGreen()) * 0.6, color.GetBlue() + (255 - color.GetBlue()) * 0.6); Int width = 4 * scaleFactor; Point offset = Point(IsRightToLeft() ? 1 : 0, 0); if (i == 0) offset += Point(IsRightToLeft() ? -1 : 1, 1); Point p1 = Point(frame.left + width, frame.top + width) + offset; Point p2 = Point(frame.left + frame.GetHeight() - width, frame.bottom - width) + offset; surface->Line(p1 + Point(0, 0), p2 + Point( 0, 0), color); surface->Line(p1 + Point(1, 0), p2 + Point( 0, -1), color); surface->Line(p1 + Point(0, 1), p2 + Point(-1, 0), color); p1 = Point(frame.left + frame.GetHeight() - width - 1, frame.top + width) + offset; p2 = Point(frame.left + width - 1, frame.bottom - width) + offset; surface->Line(p1 + Point( 0, 0), p2 + Point(0, 0), color); surface->Line(p1 + Point( 0, 1), p2 + Point(1, 0), color); surface->Line(p1 + Point(-1, 0), p2 + Point(0, -1), color); } } break; } surface->EndPaint(); return Success(); } S::Void S::GUI::PopupMenuEntryCheck::OnClickEntry() { *bVar = !*bVar; CheckBox::internalCheckValues.Emit(); PopupMenuEntry::OnClickEntry(); } S::Bool S::GUI::PopupMenuEntryCheck::IsTypeCompatible(Short compType) const { if (compType == PopupMenuEntry::classID) return True; else return PopupMenuEntry::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/menu/popupmenuentryoption.cpp000077500000000000000000000055171516402577000310270ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include const S::Short S::GUI::PopupMenuEntryOption::classID = S::Object::RequestClassID(); S::GUI::PopupMenuEntryOption::PopupMenuEntryOption(const String &iText, Int *iiVar, Int iiCode) : PopupMenuEntry(iText) { type = classID; iVar = iiVar; iCode = iiCode; } S::GUI::PopupMenuEntryOption::~PopupMenuEntryOption() { } S::Int S::GUI::PopupMenuEntryOption::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); surface->StartPaint(frame); PopupMenuEntry::Paint(message); switch (message) { case SP_PAINT: case SP_MOUSEIN: case SP_MOUSEOUT: if (*iVar == iCode) { Float scaleFactor = surface->GetSurfaceDPI() / 96.0; for (Int j = 0; j < 2; j++) { Color color = (IsActive() ? Setup::TextColor : Setup::InactiveTextColor); Point offset = Point(IsRightToLeft() ? 1 : 0, 0); if (message == SP_MOUSEIN) color = Setup::GradientTextColor; if (j == 0) { color = Color(color.GetRed() + (255 - color.GetRed()) * 0.6, color.GetGreen() + (255 - color.GetGreen()) * 0.6, color.GetBlue() + (255 - color.GetBlue()) * 0.6); offset = Point(IsRightToLeft() ? -1 : 1, 1); } Int inset = 1 * scaleFactor; Point lineStart = Point(frame.left, frame.top) + Point(4, 4) * scaleFactor + offset + Point(inset + 2, 0); Point lineEnd = lineStart + Point(5 * scaleFactor - 2 * inset - 2, 0); for (Int i = 0; i < 5 * scaleFactor; i++) { if (i <= inset) { lineStart.x--; lineEnd.x++; } else if (i >= (5 * scaleFactor) - inset) { lineStart.x++; lineEnd.x--; } lineStart.y++; lineEnd.y++; surface->Line(lineStart, lineEnd, color); } } } break; } surface->EndPaint(); return Success(); } S::Void S::GUI::PopupMenuEntryOption::OnClickEntry() { *iVar = iCode; OptionBox::internalCheckValues.Emit(); PopupMenuEntry::OnClickEntry(); } S::Bool S::GUI::PopupMenuEntryOption::IsTypeCompatible(Short compType) const { if (compType == PopupMenuEntry::classID) return True; else return PopupMenuEntry::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/tree/000077500000000000000000000000001516402577000237405ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/tree/Makefile000066400000000000000000000004521516402577000254010ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. # Enter object files here: OBJECTS = tree.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/multi/tree/tree.cpp000077500000000000000000000236171516402577000254170ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include const S::Short S::GUI::Tree::classID = S::Object::RequestClassID(); S::GUI::Tree::Tree(const String &iText) : ListEntry(iText) { type = classID; list.SetFlags(LF_ALLOWRESELECT); list.onSelectEntry.Connect(&onSelectEntry); Add(&list); headHotspot = new Hotspot(Point(), Size(GetWidth(), 16)); headHotspot->onMouseOver.Connect(&Tree::OnMouseOver, this); headHotspot->onMouseOut.Connect(&Tree::OnMouseOut, this); headHotspot->onLeftButtonDown.Connect(&onSelect); Add(headHotspot); hotspot->onLeftButtonDown.Disconnect(&ListEntry::OnSelectEntry, this); internalOnSelectEntry.Connect(&Tree::OnSelectEntry, this); onChangeSize.Connect(&Tree::OnChangeSize, this); onToggleMark.Connect(&Tree::OnToggleMark, this); } S::GUI::Tree::~Tree() { internalOnSelectEntry.Disconnect(&Tree::OnSelectEntry, this); DeleteObject(headHotspot); if (IsRegistered() && container != NIL) container->Remove(this); } S::Int S::GUI::Tree::Add(Widget *widget) { if (widget == NIL) return Error(); if (widget->GetObjectType() == ListEntry::classID) return list.Add(widget); return Widget::Add(widget); } S::Int S::GUI::Tree::Remove(Widget *widget) { if (widget == NIL) return Error(); if (widget->GetObjectType() == ListEntry::classID) return list.Remove(widget); return Widget::Remove(widget); } S::Void S::GUI::Tree::CalculateHeight() { /* Calculate tree height. */ Int height = 16; if (IsMarked()) { for (Int i = 0; i < Length(); i++) height += GetNthEntry(i)->GetHeight(); } /* Set new height if changed. */ if (height == GetHeight()) return; SetHeight(height); /* Recalculate parent trees. */ if (!IsRegistered()) return; Widget *widget = container; while (widget->GetObjectType() != ListBox::classID) { if (widget->GetObjectType() == Tree::classID) { ((Tree *) widget)->CalculateHeight(); break; } widget = widget->GetContainer(); } } S::Int S::GUI::Tree::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Window *window = container->GetContainerWindow(); CalculateHeight(); switch (message) { case SP_PAINT: surface->StartPaint(GetVisibleArea()); if (!IsMarked()) list.Hide(); if (window->IsMouseOn(Rect(Point(frame.left, frame.top), Size(frame.GetWidth(), Math::Round(16 * surface->GetSurfaceDPI() / 96.0))))) PaintText(Setup::GradientTextColor, True); else PaintText(active ? font.GetColor() : Setup::InactiveTextColor, False); if (IsMarked()) { list.SetVisibleDirect(False); list.SetMetrics(Point(12, 16), GetSize() - Size(12, 15)); Rect visibleArea = list.GetVisibleArea() - list.GetRealPosition(); Point entryPosition = Point(0, 0); Point entryRealPosition = Point(0, 0); for (Int i = 0; i < Length(); i++) { ListEntry *entry = GetNthEntry(i); Size entryRealSize = entry->GetRealSize(); entry->SetVisibleDirect(False); if (entryRealPosition.y + entryRealSize.cy >= visibleArea.top && entryRealPosition.y <= visibleArea.bottom) { entry->SetMetrics(entryPosition, Size(list.GetWidth(), entry->GetHeight())); entry->SetVisibleDirect(True); /* Draw horizontal branch line. */ Point startPos = GetRealPosition() + Point(Math::Round(6 * surface->GetSurfaceDPI() / 96.0) + (IsRightToLeft() ? 1 : 0), entryRealPosition.y + Math::Round(8 * surface->GetSurfaceDPI() / 96.0) + Math::Round(16 * surface->GetSurfaceDPI() / 96.0)); for (Int x = 0; x < Math::Round(5 * surface->GetSurfaceDPI() / 96.0); x += 2) { surface->SetPixel(startPos + Point(x, 0), Setup::InactiveTextColor); } } /* Compute next entry position. */ if (i < Length() - 1) { entryPosition.y += entry->GetHeight(); entryRealPosition.y = Math::Round(entryPosition.y * surface->GetSurfaceDPI() / 96.0); } } list.SetVisibleDirect(True); list.Paint(SP_PAINT); /* Draw vertical dotted line. */ Point startPos = frame.GetPosition() + Point(Math::Round(6 * surface->GetSurfaceDPI() / 96.0) + (IsRightToLeft() ? 1 : 0), Math::Round(16 * surface->GetSurfaceDPI() / 96.0)); for (Int i = visibleArea.top - visibleArea.top % 2; i < Math::Min(entryRealPosition.y, visibleArea.bottom) + Math::Round(9 * surface->GetSurfaceDPI() / 96.0); i += 2) { surface->SetPixel(startPos + Point(0, i), Setup::InactiveTextColor); } } surface->EndPaint(); break; case SP_MOUSEIN: if (window->IsMouseOn(Rect(Point(frame.left, frame.top), Size(frame.GetWidth(), Math::Round(16 * surface->GetSurfaceDPI() / 96.0))))) PaintText(Setup::GradientTextColor, True); break; case SP_MOUSEOUT: PaintText(font.GetColor(), False); break; } return Success(); } S::Void S::GUI::Tree::PaintText(const Color &color, Bool drawGradient) { Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Font nFont = font; Bool gotTabs = False; if (!active) nFont.SetColor(Setup::InactiveTextColor); else nFont.SetColor(color); if (text.Contains(ListEntry::tabDelimiter)) gotTabs = True; surface->StartPaint(GetVisibleArea()); if (drawGradient) surface->Gradient(Rect(Point(frame.left, frame.top), Size(frame.GetWidth(), Math::Round(16 * surface->GetSurfaceDPI() / 96.0))), Setup::GradientStartColor, Setup::GradientEndColor, OR_HORZ); else surface->Box(Rect(Point(frame.left, frame.top), Size(frame.GetWidth(), Math::Round(16 * surface->GetSurfaceDPI() / 96.0))), Setup::ClientColor, Rect::Filled); Rect cbRect = Rect(GetRealPosition() + Point(2, 3) * surface->GetSurfaceDPI() / 96.0, Size(9, 9) * surface->GetSurfaceDPI() / 96.0); if (cbRect.GetWidth() % 2 == 0) cbRect = cbRect + Point(1, 1) - Size(1, 1); if (cbRect.top <= cbRect.bottom - 1) { surface->Box(cbRect, Setup::ClientColor, Rect::Filled); surface->Box(cbRect, Setup::InactiveTextColor, Rect::Outlined); if (cbRect.top <= cbRect.bottom - 3) { Point p1 = Point(cbRect.left + 2 + (IsRightToLeft() ? 1 : 0), (cbRect.top + cbRect.bottom) / 2); Point p2 = Point(cbRect.right - 2 + (IsRightToLeft() ? 1 : 0), (cbRect.top + cbRect.bottom) / 2); Color darkColor = Setup::ClientTextColor; if (!active) darkColor = Setup::InactiveTextColor; surface->Line(p1, p2, darkColor); if (!IsMarked()) { p1 = Point((cbRect.left + cbRect.right) / 2 + (IsRightToLeft() ? 1 : 0), cbRect.top + 2); p2 = Point((cbRect.left + cbRect.right) / 2 + (IsRightToLeft() ? 1 : 0), cbRect.bottom - 2); surface->Line(p1, p2, darkColor); } } } if (container->GetObjectType() == ListBox::classID && ((ListBox *) container)->GetNOfTabs() > 0 && gotTabs) { for (Int i = 0; i < ((ListBox *) container)->GetNOfTabs(); i++) { Rect rect = Rect(GetRealPosition() + Point(0, Math::Ceil(Float(headHotspot->GetRealSize().cy - nFont.GetScaledTextSizeY()) / 2) - 2) + Point(1, 1) * surface->GetSurfaceDPI() / 96.0, GetSize() - Size(1, 1) * surface->GetSurfaceDPI() / 96.0 * 2 - Size(1, 0)); rect.left += ((ListBox *) container)->GetNthTabOffset(i); rect.left += (i == 0 ? Math::Round(12 * surface->GetSurfaceDPI() / 96.0) : 0); if (((ListBox *) container)->GetNOfTabs() >= i + 2) rect.right = rect.left + (((ListBox *) container)->GetNthTabOffset(i + 1) - ((ListBox *) container)->GetNthTabOffset(i)) - (i == 0 ? Math::Round(12 * surface->GetSurfaceDPI() / 96.0) : 0) - Math::Round(1 * surface->GetSurfaceDPI() / 96.0) * 2 - 1; String tabText = GetNthTabText(i); if (((ListBox *) container)->GetNthTabOrientation(i) == OR_RIGHT) { rect.left = Math::Max(rect.left, rect.right - nFont.GetScaledTextSizeX(tabText)); } surface->SetText(tabText, rect, nFont); } } else { surface->SetText(text, frame + Point(0, Math::Ceil(Float(headHotspot->GetRealSize().cy - nFont.GetScaledTextSizeY()) / 2) - 2) + Point(1, 1) * surface->GetSurfaceDPI() / 96.0 + Point(Math::Round(12 * surface->GetSurfaceDPI() / 96.0), 0) - Size(1, 1) * surface->GetSurfaceDPI() / 96.0 * 2 - Size(Math::Round(12 * surface->GetSurfaceDPI() / 96.0), 0), nFont); } surface->EndPaint(); } S::Void S::GUI::Tree::OnSelectEntry(Int containerHandle, Int handle) { if (!IsRegistered()) return; if (containerHandle == list.GetHandle() && handle != GetHandle()) internalOnSelectEntry.Emit(container->GetHandle(), GetHandle()); else if (containerHandle == container->GetHandle() && handle != GetHandle()) internalOnSelectEntry.Emit(list.GetHandle(), GetHandle()); } S::Void S::GUI::Tree::OnChangeSize(const Size &newSize) { headHotspot->SetWidth(newSize.cx); } S::Void S::GUI::Tree::OnToggleMark(Bool marked) { if (marked) onOpen.Emit(); else onClose.Emit(); CalculateHeight(); if (IsRegistered()) { /* Find ListBox container and repaint it. */ Widget *widget = container; while (widget != NIL && widget->GetObjectType() != ListBox::classID) widget = widget->GetContainer(); if (widget != NIL) widget->Paint(SP_PAINT); } } S::Void S::GUI::Tree::OnMouseOver() { Paint(SP_MOUSEIN); } S::Void S::GUI::Tree::OnMouseOut() { Paint(SP_MOUSEOUT); } S::Bool S::GUI::Tree::IsTypeCompatible(Short compType) const { if (compType == ListEntry::classID) return True; else return ListEntry::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/special/000077500000000000000000000000001516402577000232675ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/special/Makefile000066400000000000000000000011171516402577000247270ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifeq ($(USE_BUNDLED_LIBFRIBIDI),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support -DFRIBIDI_LIB_STATIC endif # Enter object files here: OBJECTS = cursor.o dragcontrol.o droparea.o shortcut.o tooltip.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/special/cursor.cpp000077500000000000000000001166261516402577000253270ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const S::Int CF_NOINPUT = 1 << 30; const S::Short S::GUI::Cursor::classID = S::Object::RequestClassID(); S::Signal2 S::GUI::Cursor::internalSetCursor; S::Signal1 S::GUI::Cursor::internalRemoveCursor; S::GUI::Cursor::Cursor(const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { type = classID; markStart = -1; markEnd = -1; maxSize = 32768; promptPos = 0; promptVisible = False; timer = NIL; marking = False; visibleOffset = 0; scrollPos = 0; maxScrollPos = 0; contextMenu = NIL; historyPos = 0; tabSize = 4; imeAdvance = 0; imeCursor = False; SetTabstopCapable(True); onGetFocus.Connect(&Cursor::OnGetFocus, this); onGetFocusByKeyboard.Connect(&Cursor::OnGetFocusByKeyboard, this); onLoseFocus.Connect(&Cursor::OnLoseFocus, this); getContextMenu.Connect(&Cursor::GetContextMenu, this); onInput.SetParentObject(this); onEnter.SetParentObject(this); onScroll.SetParentObject(this); AddHistoryEntry(); } S::GUI::Cursor::~Cursor() { if (contextMenu != NIL) DeleteObject(contextMenu); if (timer != NIL) DeleteObject(timer); } S::Int S::GUI::Cursor::Paint(Int message) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); switch (message) { case SP_PAINT: DrawWidget(); break; case SP_MOUSEIN: Input::Pointer::SetCursor(container->GetContainerWindow(), Input::Pointer::CursorTextEdit); break; case SP_MOUSEOUT: Input::Pointer::SetCursor(container->GetContainerWindow(), Input::Pointer::CursorArrow); break; } return Success(); } S::Int S::GUI::Cursor::Process(Int message, Int wParam, Int lParam) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Window *window = container->GetContainerWindow(); if (window == NIL) return Success(); switch (message) { case SM_LBUTTONDOWN: if (mouseOver) { Rect frame = Rect(GetRealPosition(), GetRealSize()); String wText = text; Int wPromptPos = 0; if (Binary::IsFlagSet(GetFlags(), CF_MULTILINE)) { Int line = (window->GetMousePosition().y - frame.top) / (font.GetScaledTextSizeY() + 3); Int lineCount = 0; Int length = text.Length(); for (Int i = 0; i <= length; i++) { wText[i - wPromptPos] = text[i]; if (text[i] == '\n' || text[i] == 0) { wText[i - wPromptPos] = 0; if (lineCount - scrollPos == line || text[i] == 0) break; wPromptPos = i + 1; lineCount++; } } } Int newPromptPos = GetLogicalCursorPositionFromDisplay(wText, window->GetMousePosition().x - frame.left) + wPromptPos; marking = True; if (Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) { if (markStart == -1) markStart = GetCursorPos(); if (markStart == -1) markStart = newPromptPos; MarkText(markStart, newPromptPos); } else { MarkText(newPromptPos, newPromptPos); } SetCursorPos(newPromptPos); if (!focussed) { focussed = True; onGetFocus.Emit(); } else { onClickInFocus.Emit(); } } else { if (focussed) { focussed = False; onLoseFocus.Emit(); } } break; case SM_LBUTTONUP: if (focussed && markStart != -1) { if (markStart == markEnd) { markStart = -1; markEnd = -1; } marking = False; } break; case SM_LBUTTONDBLCLK: if (focussed) { /* Compute word start and end. */ Int length = text.Length(); Int wordStart = 0; Int wordEnd = length; for (Int i = promptPos - 2; i >= 0; i--) { if ( ( text[i + 1] == '\n') || ((text[i ] == ' ' || text[i ] == '\t' || text[i ] == '\n') && (text[i + 1] != ' ' && text[i + 1] != '\t' && text[i + 1] != '\n'))) { wordStart = i + 1; break; } } for (Int i = promptPos - 1; i < length; i++) { if ( ( text[i + 1] == '\n') || ((text[i ] == ' ' || text[i ] == '\t' || text[i ] == '\n') && (text[i + 1] != ' ' && text[i + 1] != '\t' && text[i + 1] != '\n'))) { wordEnd = i + 1; break; } } /* Set mark region. */ if (Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) { if (markStart == -1) markStart = promptPos; if (promptPos <= markStart) { MarkText(markStart, wordStart); SetCursorPos(wordStart); } else { MarkText(markStart, wordEnd); SetCursorPos(wordEnd); } } else { MarkText(wordStart, wordEnd); SetCursorPos(wordEnd); } } break; case SM_RBUTTONDOWN: case SM_RBUTTONDBLCLK: if (mouseOver) { /* Activate this widget before opening the context menu. */ if (!focussed) { window->Process(SM_LBUTTONDOWN, 0, 0); window->Process(SM_LBUTTONUP, 0, 0); } /* Enable the context menu even for inactive widgets. */ if (!IsActive()) { OpenContextMenu(); /* Force mouseOut event. */ window->Process(SM_MOUSEMOVE, 0, 0); } } break; case SM_MBUTTONDOWN: if (focussed && IsActive() && Clipboard(container->GetContainerWindow()).GetSelectionText() != NIL) { Bool selected = (markStart != markEnd && markStart >= 0 && markEnd >= 0); flags |= CF_NOINPUT; DeleteSelectedText(); flags ^= CF_NOINPUT; String insertText = Clipboard(container->GetContainerWindow()).GetSelectionText(); if (insertText.Length() > 0 && (insertText.Length() + text.Length()) <= maxSize) { if (Binary::IsFlagSet(container->GetFlags(), EDB_NUMERIC) && (insertText.ToInt() == 0 && insertText[0] != '0')) break; if (selected) RemoveHistoryEntry(); InsertText(insertText); } onInput.Emit(text); } break; case SM_MOUSEMOVE: { Rect frame = Rect(GetRealPosition(), GetRealSize()); if (!mouseOver && window->IsMouseOn(frame)) { mouseOver = True; Paint(SP_MOUSEIN); } else if (mouseOver && !window->IsMouseOn(frame)) { mouseOver = False; Paint(SP_MOUSEOUT); } if (focussed && markStart != -1 && marking) { String wText = text; Int wPromptPos = 0; if (Binary::IsFlagSet(GetFlags(), CF_MULTILINE)) { Int line = (window->GetMousePosition().y - frame.top) / (font.GetScaledTextSizeY() + 3); Int lineCount = 0; Int length = text.Length(); if (window->GetMousePosition().y - frame.top < 0) line--; for (Int i = 0; i <= length; i++) { wText[i - wPromptPos] = text[i]; if (text[i] == '\n' || text[i] == 0) { wText[i - wPromptPos] = 0; if (lineCount - scrollPos == line || text[i] == 0) break; wPromptPos = i + 1; lineCount++; } } if (lineCount - scrollPos != line) wPromptPos = -1; } if (wPromptPos >= 0) { Int newMarkEnd = GetLogicalCursorPositionFromDisplay(wText, window->GetMousePosition().x - frame.left) + wPromptPos; MarkText(markStart, newMarkEnd); SetCursorPos(newMarkEnd); } } } break; case SM_KEYDOWN: if (OnSpecialKey(wParam)) return MessageProcessed; break; case SM_CHAR: OnInput(wParam, lParam); break; } return Widget::Process(message, wParam, lParam); } S::Int S::GUI::Cursor::DrawWidget() { Int nMaxScrollPos = Math::Max(0, (Int) Math::Ceil((Float) (font.GetUnscaledTextSizeY(text) - GetHeight()) / (font.GetUnscaledTextSizeY() + 3))); if (nMaxScrollPos != maxScrollPos) { maxScrollPos = nMaxScrollPos; if (maxScrollPos == 0) scrollPos = 0; onScroll.Emit(scrollPos, maxScrollPos); } Int textLength = text.Length(); if (lineIndices.Length() == 0) { lineIndices.Add(0); for (Int i = 0; i <= textLength; i++) { if (text[i] != '\n' && text[i] != 0) continue; lineIndices.Add(i + 1); } } Surface *surface = GetDrawSurface(); Point realPos = GetRealPosition(); Rect frame = Rect(realPos, GetRealSize()); surface->StartPaint(GetVisibleArea()); surface->Box(frame, GetBackgroundColor(), Rect::Filled); Int lineNumber = scrollPos; for (Int lineStart = lineIndices.GetNth(lineNumber); lineStart <= textLength; lineStart = lineIndices.GetNth(++lineNumber)) { if ((lineNumber - scrollPos) * (font.GetUnscaledTextSizeY() + 3) >= frame.GetHeight()) break; Int lineLength = lineIndices.GetNth(lineNumber + 1) - lineStart - 1; String line = text.SubString(lineStart, lineLength); if (!Binary::IsFlagSet(container->GetFlags(), EDB_ASTERISK)) surface->SetText(ConvertTabs(line, tabSize), frame + Point(-visibleOffset, (lineNumber - scrollPos) * (font.GetScaledTextSizeY() + 3)) + Point(0, 1) * surface->GetSurfaceDPI() / 96.0 + Size(visibleOffset, -2), font); else surface->SetText(String().FillN('*', lineLength), frame + Point(-visibleOffset, (lineNumber - scrollPos) * (font.GetScaledTextSizeY() + 3)) + Point(0, 1) * surface->GetSurfaceDPI() / 96.0 + Size(visibleOffset, -2), font); if (markStart != markEnd && markStart >= 0 && markEnd >= 0) { Int lineMarkStart = Math::Max(0, Math::Min(markStart, markEnd) - lineStart); Int lineMarkEnd = Math::Min(lineLength, Math::Max(markStart, markEnd) - lineStart); if (lineMarkStart < lineLength && lineMarkEnd > 0) { Array markRegionStarts; Array markRegionEnds; if (Setup::useIconv && ContainsRTLCharacters(line)) { FriBidiStrIndex length = lineLength; /* Get visual positions. */ FriBidiStrIndex *positions = new FriBidiStrIndex [length + 1]; FriBidiParType type = (IsRightToLeft() ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR); fribidi_log2vis((FriBidiChar *) line.ConvertTo("UCS-4LE"), length, &type, NIL, positions, NIL, NIL); /* Find marked regions in visual string. */ for (Int i = lineMarkStart; i < lineMarkEnd; i++) { Bool done = False; for (Int j = 0; j < markRegionStarts.Length(); j++) { if (markRegionStarts.GetNth(j) == positions[i] + 1) { markRegionStarts.SetNth(j, markRegionStarts.GetNth(j) - 1); done = True; break; } else if (markRegionEnds.GetNth(j) == positions[i] ) { markRegionEnds.SetNth(j, markRegionEnds.GetNth(j) + 1); done = True; break; } } if (!done) { markRegionStarts.Add(positions[i]); markRegionEnds.Add(positions[i] + 1); } } delete [] positions; /* Consolidate adjacent regions into one. */ for (Int i = 0; i < markRegionStarts.Length() - 1; i++) { for (Int j = i + 1; j < markRegionStarts.Length(); j++) { if (markRegionStarts.GetNth(i) < markRegionStarts.GetNth(j) && markRegionEnds.GetNth(i) >= markRegionStarts.GetNth(j)) { markRegionEnds.SetNth(i, markRegionEnds.GetNth(j)); markRegionStarts.RemoveNth(j); markRegionEnds.RemoveNth(j); j--; } else if (markRegionStarts.GetNth(j) < markRegionStarts.GetNth(i) && markRegionEnds.GetNth(j) >= markRegionStarts.GetNth(i)) { markRegionStarts.SetNth(i, markRegionStarts.GetNth(j)); markRegionStarts.RemoveNth(j); markRegionEnds.RemoveNth(j); j--; } } } } else { markRegionStarts.Add(lineMarkStart); markRegionEnds.Add(lineMarkEnd); } /* Draw marked regions. */ for (Int i = 0; i < markRegionStarts.Length(); i++) { Int markRegionStart = GetDisplayCursorPositionFromVisual(line, markRegionStarts.GetNth(i)); Int markRegionEnd = GetDisplayCursorPositionFromVisual(line, markRegionEnds.GetNth(i)); Rect markRect = Rect(realPos + Point(Math::Min(markRegionStart, markRegionEnd), (lineNumber - scrollPos) * (font.GetScaledTextSizeY() + 3)) + Point(0, 1) * surface->GetSurfaceDPI() / 96.0 - Point(0, 1), Size(Math::Abs(markRegionEnd - markRegionStart), font.GetScaledTextSizeY() + 3)); Font nFont = font; nFont.SetColor(Setup::HighlightTextColor); surface->StartPaint(markRect); surface->Box(markRect, Setup::HighlightColor, Rect::Filled); if (!Binary::IsFlagSet(container->GetFlags(), EDB_ASTERISK)) surface->SetText(ConvertTabs(line, tabSize), frame + Point(-visibleOffset, (lineNumber - scrollPos) * (font.GetScaledTextSizeY() + 3)) + Point(0, 1) * surface->GetSurfaceDPI() / 96.0 + Size(visibleOffset, -2), nFont); else surface->SetText(String().FillN('*', lineLength), frame + Point(-visibleOffset, (lineNumber - scrollPos) * (font.GetScaledTextSizeY() + 3)) + Point(0, 1) * surface->GetSurfaceDPI() / 96.0 + Size(visibleOffset, -2), nFont); surface->EndPaint(); } } } } surface->EndPaint(); return Success(); } S::Void S::GUI::Cursor::ShowCursor(Bool visible) { /* Cancel if cursor is displayed by the IME. */ if (imeCursor) return; /* Cancel if cursor is already in the desired state. */ if (promptVisible == visible) return; Surface *surface = GetDrawSurface(); Point point = GetRealPosition(); Int line = 0; if (Binary::IsFlagSet(GetFlags(), CF_MULTILINE)) { for (Int j = promptPos - 1; j >= 0; j--) { if (text[j] == '\n') line++; } } point.x += GetDisplayCursorPositionFromLogical(promptPos) + imeAdvance; point.y += (font.GetScaledTextSizeY() + 3) * (line - scrollPos); if (!(Binary::IsFlagSet(GetFlags(), CF_MULTILINE) && (line - scrollPos < 0 || (font.GetUnscaledTextSizeY() + 3) * (line - scrollPos + 1) > GetHeight()))) { if (IsVisible()) surface->Box(Rect(point, Size(1, font.GetScaledTextSizeY() + 3)), 0, Rect::Inverted); promptVisible = visible; } } S::Int S::GUI::Cursor::SetText(const String &newText) { if (text == newText) return Success(); Surface *surface = GetDrawSurface(); Rect frame = Rect(GetRealPosition(), GetRealSize()); Bool visible = IsVisible(); if (visible) surface->StartPaint(frame); ShowCursor(False); MarkText(-1, -1); lineIndices.RemoveAll(); if (timer != NIL) { DeleteObject(timer); timer = NIL; } promptPos = newText.Length(); visibleOffset = 0; scrollPos = 0; ClearHistory(); Widget::SetText(newText); if (IsActive()) AddHistoryEntry(); if (visible) surface->EndPaint(); return Success(); } S::Void S::GUI::Cursor::MarkText(Int newMarkStart, Int newMarkEnd) { if (newMarkStart == markStart && newMarkEnd == markEnd) return; ShowCursor(False); markStart = newMarkStart; markEnd = newMarkEnd; Paint(SP_PAINT); /* Copy selected text to selection clipboard. */ if (Math::Abs(markEnd - markStart) > 0) Clipboard(container->GetContainerWindow()).SetSelectionText(text.SubString(Math::Min(markStart, markEnd), Math::Abs(markEnd - markStart))); } S::Int S::GUI::Cursor::MarkAll() { MarkText(0, text.Length()); SetCursorPos(text.Length()); return Success(); } S::Void S::GUI::Cursor::InsertText(const String &insertText) { ShowCursor(False); Int textLength = text.Length(); Int insertLength = insertText.Length(); /* Build resulting text value. */ String newText; for (Int i = 0; i < promptPos; i++) newText[i] = text[i]; for (Int i = promptPos; i < promptPos + insertLength; i++) newText[i] = insertText[i - promptPos]; for (Int i = promptPos; i <= textLength; i++) newText[i + insertLength] = text[i]; /* Draw widget with new content. */ Bool prevVisible = IsVisible(); visible = False; lineIndices.RemoveAll(); Widget::SetText(newText); visible = prevVisible; /* Update screen. */ Surface *surface = GetDrawSurface(); surface->StartPaint(Rect(container->GetRealPosition(), container->GetRealSize())); container->Paint(SP_PAINT); surface->EndPaint(); /* Update cursor position. */ SetCursorPos(promptPos + insertLength); AddHistoryEntry(); } S::Void S::GUI::Cursor::CopyToClipboard() { if (markStart != markEnd) { Clipboard(container->GetContainerWindow()).SetClipboardText(text.SubString(Math::Min(markStart, markEnd), Math::Abs(markEnd - markStart))); } } S::Void S::GUI::Cursor::InsertFromClipboard() { Bool selected = (markStart != markEnd && markStart >= 0 && markEnd >= 0); flags |= CF_NOINPUT; DeleteSelectedText(); flags ^= CF_NOINPUT; String insertText = Clipboard(container->GetContainerWindow()).GetClipboardText(); if (insertText.Length() > 0 && (insertText.Length() + text.Length()) <= maxSize) { if (Binary::IsFlagSet(container->GetFlags(), EDB_NUMERIC) && (insertText.ToInt() == 0 && insertText[0] != '0')) return; if (selected) RemoveHistoryEntry(); InsertText(insertText); } onInput.Emit(text); } S::Void S::GUI::Cursor::DeleteSelectedText() { if (markStart == markEnd || markStart < 0 || markEnd < 0) return; ShowCursor(False); Int bMarkStart = Math::Min(markStart, markEnd); Int bMarkEnd = Math::Max(markStart, markEnd); Bool prevVisible = IsVisible(); visible = False; MarkText(-1, -1); String newText; for (Int i = 0; i < bMarkStart; i++) newText[i] = text[i]; for (Int j = bMarkEnd; j <= text.Length(); j++) newText[j - (bMarkEnd - bMarkStart)] = text[j]; lineIndices.RemoveAll(); Widget::SetText(newText); visible = prevVisible; Surface *surface = GetDrawSurface(); surface->StartPaint(Rect(container->GetRealPosition(), container->GetRealSize())); container->Paint(SP_PAINT); surface->EndPaint(); SetCursorPos(bMarkStart); AddHistoryEntry(); if(!Binary::IsFlagSet(GetFlags(), CF_NOINPUT)) onInput.Emit(newText); } S::Int S::GUI::Cursor::Scroll(Int nScrollPos) { ShowCursor(False); scrollPos = Math::Max(0, Math::Min(nScrollPos, maxScrollPos)); Paint(SP_PAINT); onScroll.Emit(scrollPos, maxScrollPos); return Success(); } S::Void S::GUI::Cursor::OnTimer() { ShowCursor(!promptVisible); } S::Void S::GUI::Cursor::OnGetFocus() { SetCursorPos(promptPos); } S::Void S::GUI::Cursor::OnGetFocusByKeyboard() { MarkAll(); } S::Void S::GUI::Cursor::OnLoseFocus() { ShowCursor(False); MarkText(-1, -1); if (timer != NIL) { DeleteObject(timer); timer = NIL; } /* Notify listeners of removed cursor. */ internalRemoveCursor.Emit(this); } S::Bool S::GUI::Cursor::OnSpecialKey(Int keyCode) { /* Called when a special key such as * return or an arrow key is hit. */ if (!focussed) return False; #if defined __APPLE__ Input::Keyboard::Key commandKey = Input::Keyboard::KeyCommand; #elif defined __HAIKU__ Input::Keyboard::Key commandKey = Input::Keyboard::KeyAlt; #else Input::Keyboard::Key commandKey = Input::Keyboard::KeyControl; #endif /* Make sure no other modifiers are pressed along with command key. */ if (Input::Keyboard::GetKeyState(commandKey) && !(Input::Keyboard::GetKeyState(Input::Keyboard::KeyCommand) ^ Input::Keyboard::GetKeyState(Input::Keyboard::KeyControl) ^ Input::Keyboard::GetKeyState(Input::Keyboard::KeyAlt))) return False; /* Evaluate key code. */ Int newPos = 0; Int linePos = 0; Int i = 0; switch (keyCode) { case Input::Keyboard::KeyLeft: case Input::Keyboard::KeyRight: if (!Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) MarkText(-1, -1); /* Calculate new cursor pos. */ if (Input::Keyboard::GetKeyState(commandKey)) { Bool isLeft = ((keyCode == Input::Keyboard::KeyLeft && !IsRightToLeft()) || (keyCode == Input::Keyboard::KeyRight && IsRightToLeft())); if (isLeft) { newPos = 0; for (Int i = promptPos - 2; i >= 0; i--) { if ( ( text[i + 1] == '\n') || ((text[i ] == ' ' || text[i ] == '\t' || text[i ] == '\n') && (text[i + 1] != ' ' && text[i + 1] != '\t' && text[i + 1] != '\n'))) { newPos = i + 1; break; } } } else { newPos = text.Length(); for (Int i = promptPos; i < text.Length(); i++) { if ( ( text[i + 1] == '\n') || ((text[i ] == ' ' || text[i ] == '\t' || text[i ] == '\n') && (text[i + 1] != ' ' && text[i + 1] != '\t' && text[i + 1] != '\n'))) { newPos = i + 1; break; } } } } else { Bool isLeft = ((keyCode == Input::Keyboard::KeyLeft && !IsRightToLeft()) || (keyCode == Input::Keyboard::KeyRight && IsRightToLeft())); if (isLeft) { if (promptPos == 0) break; newPos = promptPos - 1; } else { if (promptPos >= text.Length()) break; newPos = promptPos + 1; } } /* Set mark region and cursor. */ if (Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) { if (markStart == -1) markStart = promptPos; MarkText(markStart, newPos); } SetCursorPos(newPos); break; case Input::Keyboard::KeyHome: case Input::Keyboard::KeyEnd: if (!Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) MarkText(-1, -1); /* Calculate new cursor pos. */ if (Input::Keyboard::GetKeyState(commandKey)) { if (keyCode == Input::Keyboard::KeyHome) { if (promptPos == 0) break; newPos = 0; } else if (keyCode == Input::Keyboard::KeyEnd) { if (promptPos >= text.Length()) break; newPos = text.Length(); } } else { if (keyCode == Input::Keyboard::KeyHome) { newPos = 0; for (Int i = promptPos - 1; i >= 0; i--) { if (text[i] == '\n') { newPos = i + 1; break; } } } else { newPos = text.Length(); for (Int i = promptPos; i < text.Length(); i++) { if (text[i] == '\n') { newPos = i; break; } } } } /* Set mark region and cursor. */ if (Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) { if (markStart == -1) markStart = promptPos; MarkText(markStart, newPos); } SetCursorPos(newPos); break; case Input::Keyboard::KeyUp: case Input::Keyboard::KeyDown: if (!Binary::IsFlagSet(GetFlags(), CF_MULTILINE)) break; if (!Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) MarkText(-1, -1); /* Calculate new cursor pos. */ linePos = promptPos; newPos = promptPos; for (i = promptPos - 1; i >= 0; i--) { if (text[i] == '\n') { linePos -= (i + 1); break; } } if (keyCode == Input::Keyboard::KeyUp) { if (i == 0) newPos = 0; for (Int j = i - 1; j >= 0; j--) { if (text[j] == '\n' || j == 0) { newPos = Math::Min(i, j + linePos + (j == 0 ? 0 : 1)); break; } } } else { for (Int j = promptPos; j < text.Length(); j++) { if (text[j] == '\n') { for (Int k = j + 1; k <= j + 1 + linePos; k++) { newPos = k; if (text[k] == '\n' || text[k] == 0) break; } break; } } } /* Set mark region and cursor. */ if (Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) { if (markStart == -1) markStart = promptPos; MarkText(markStart, newPos); } SetCursorPos(newPos); break; case Input::Keyboard::KeyReturn: if (!IsActive()) break; if (Binary::IsFlagSet(GetFlags(), CF_MULTILINE)) { Bool selected = (markStart != markEnd && markStart >= 0 && markEnd >= 0); flags |= CF_NOINPUT; DeleteSelectedText(); flags ^= CF_NOINPUT; if (selected) RemoveHistoryEntry(); String insertText; insertText[0] = '\n'; InsertText(insertText); onInput.Emit(text); } else { focussed = False; onLoseFocus.Emit(); onEnter.Emit(text); } break; case Input::Keyboard::KeyEscape: if (!IsActive()) break; focussed = False; onLoseFocus.Emit(); return True; case Input::Keyboard::KeyInsert: #ifndef __APPLE__ if ( Input::Keyboard::GetKeyState(commandKey) && !Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) CopyToClipboard(); if (IsActive() && !Input::Keyboard::GetKeyState(commandKey) && Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) InsertFromClipboard(); #endif break; case Input::Keyboard::KeyBack: if (!IsActive() || Input::Keyboard::GetKeyState(commandKey) || Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) break; if (markStart != markEnd) { DeleteSelectedText(); break; } if (promptPos == 0) break; markStart = promptPos - 1; markEnd = promptPos; DeleteSelectedText(); break; case Input::Keyboard::KeyDelete: if (!IsActive() || Input::Keyboard::GetKeyState(commandKey)) break; #ifdef __APPLE__ if (Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) break; #endif if (markStart != markEnd) { if (Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) CopyToClipboard(); DeleteSelectedText(); break; } if (Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) break; if (promptPos == text.Length()) break; markStart = promptPos; markEnd = promptPos + 1; DeleteSelectedText(); break; case Input::Keyboard::KeyA: if ( Input::Keyboard::GetKeyState(commandKey)) MarkAll(); break; case Input::Keyboard::KeyC: if ( Input::Keyboard::GetKeyState(commandKey)) CopyToClipboard(); break; case Input::Keyboard::KeyX: if (IsActive() && Input::Keyboard::GetKeyState(commandKey)) { CopyToClipboard(); DeleteSelectedText(); } break; case Input::Keyboard::KeyV: if (IsActive() && Input::Keyboard::GetKeyState(commandKey)) InsertFromClipboard(); break; case Input::Keyboard::KeyZ: if (IsActive() && Input::Keyboard::GetKeyState(commandKey)) Undo(); break; case Input::Keyboard::KeyY: if (IsActive() && Input::Keyboard::GetKeyState(commandKey)) Redo(); break; } return False; } S::Void S::GUI::Cursor::OnInput(Int character, Int flags) { /* Called when a character is entered. */ if (!focussed) return; if (text.Length() == maxSize && markStart == markEnd) return; if (character >= 0x20 && character != 0x7F && IsActive()) { Bool selected = (markStart != markEnd && markStart >= 0 && markEnd >= 0); this->flags |= CF_NOINPUT; DeleteSelectedText(); this->flags ^= CF_NOINPUT; if (!Binary::IsFlagSet(container->GetFlags(), EDB_NUMERIC) || (character >= '0' && character <= '9') || character == '-' || character == '.') { String insertText; insertText[0] = character; if (selected) RemoveHistoryEntry(); InsertText(insertText); } onInput.Emit(text); } } S::Void S::GUI::Cursor::OnCut() { CopyToClipboard(); DeleteSelectedText(); } S::Void S::GUI::Cursor::OnInsert() { InsertFromClipboard(); } S::Void S::GUI::Cursor::AddHistoryEntry() { while (history.Length() > historyPos) { history.RemoveNth(history.Length() - 1); historyPrompt.RemoveNth(historyPrompt.Length() - 1); } history.Add(text); historyPrompt.Add(promptPos); historyPos++; } S::Void S::GUI::Cursor::RemoveHistoryEntry() { history.RemoveNth(history.Length() - 1); historyPrompt.RemoveNth(historyPrompt.Length() - 1); historyPos--; } S::Void S::GUI::Cursor::ClearHistory() { history.RemoveAll(); historyPrompt.RemoveAll(); historyPos = 0; } S::Void S::GUI::Cursor::Undo() { if (historyPos <= 1) return; lineIndices.RemoveAll(); Surface *surface = GetDrawSurface(); surface->StartPaint(GetVisibleArea()); Int index = --historyPos - 1; Widget::SetText(history.GetNth(index)); SetCursorPos(historyPrompt.GetNth(index)); surface->EndPaint(); onInput.Emit(text); } S::Void S::GUI::Cursor::Redo() { if (historyPos >= history.Length()) return; lineIndices.RemoveAll(); Surface *surface = GetDrawSurface(); surface->StartPaint(GetVisibleArea()); Int index = historyPos++; Widget::SetText(history.GetNth(index)); SetCursorPos(historyPrompt.GetNth(index)); surface->EndPaint(); onInput.Emit(text); } S::GUI::PopupMenu *S::GUI::Cursor::GetContextMenu() { if (!IsActive() && text == NIL) return NIL; if (contextMenu == NIL) contextMenu = new PopupMenu(); contextMenu->RemoveAllEntries(); MenuEntry *entryUndo = contextMenu->AddEntry(I18n::Translator::defaultTranslator->TranslateString("Undo")); contextMenu->AddEntry(); MenuEntry *entryCut = contextMenu->AddEntry(I18n::Translator::defaultTranslator->TranslateString("Cut")); MenuEntry *entryCopy = contextMenu->AddEntry(I18n::Translator::defaultTranslator->TranslateString("Copy")); MenuEntry *entryInsert = contextMenu->AddEntry(I18n::Translator::defaultTranslator->TranslateString("Paste")); MenuEntry *entryDelete = contextMenu->AddEntry(I18n::Translator::defaultTranslator->TranslateString("Clear")); contextMenu->AddEntry(); MenuEntry *entryMarkAll = contextMenu->AddEntry(I18n::Translator::defaultTranslator->TranslateString("Select all")); entryUndo->onAction.Connect(&Cursor::Undo, this); entryCut->onAction.Connect(&Cursor::OnCut, this); entryCopy->onAction.Connect(&Cursor::CopyToClipboard, this); entryInsert->onAction.Connect(&Cursor::OnInsert, this); entryDelete->onAction.Connect(&Cursor::DeleteSelectedText, this); entryMarkAll->onAction.Connect(&Cursor::MarkAll, this); /* Disable modification if inactive. */ if (!IsActive()) { entryUndo->Deactivate(); entryCut->Deactivate(); entryInsert->Deactivate(); entryDelete->Deactivate(); } /* Disable copy and delete if nothing is selected. */ if (markStart == markEnd) { entryCut->Deactivate(); entryCopy->Deactivate(); entryDelete->Deactivate(); } /* Disable "Select all" if everything is selected already. */ if ((markStart == 0 && markEnd == text.Length()) || text == NIL) { entryMarkAll->Deactivate(); } /* Disable undo if no history is available. */ if (historyPos == 1) { entryUndo->Deactivate(); } return contextMenu; } S::Int S::GUI::Cursor::SetCursorPos(Int newPos) { focussed = True; ShowCursor(False); imeAdvance = 0; imeCursor = False; Rect frame = Rect(GetRealPosition(), GetRealSize()); Point p1 = GetRealPosition(); promptPos = newPos; /* Compute line number. */ Int line = 0; if (Binary::IsFlagSet(GetFlags(), CF_MULTILINE)) { for (Int j = promptPos - 1; j >= 0; j--) { if (text[j] == '\n') line++; } } /* Compute cursor position on screen. */ p1.x += GetDisplayCursorPositionFromLogical(promptPos); while (p1.x > frame.right || p1.x < frame.left) { if (p1.x > frame.right) { visibleOffset += 5; p1.x -= 5; } else if (p1.x < frame.left) { visibleOffset -= 20; p1.x += 20; } } if (visibleOffset < 0) { p1.x -= visibleOffset; visibleOffset = 0; } p1.y += (font.GetScaledTextSizeY() + 3) * (line - scrollPos); if (Binary::IsFlagSet(GetFlags(), CF_MULTILINE) && (line - scrollPos < 0 || (font.GetUnscaledTextSizeY() + 3) * (line - scrollPos + 1) > GetHeight())) { while (line - scrollPos < 0) scrollPos--; while ((font.GetUnscaledTextSizeY() + 3) * (line - scrollPos + 1) > GetHeight()) scrollPos++; } if (maxScrollPos > 0) onScroll.Emit(scrollPos, maxScrollPos); /* Notify listeners of new cursor position. */ if (IsActive()) internalSetCursor.Emit(this, p1 + Point(1, 2)); /* Start blinking cursor timer. */ if (timer != NIL) DeleteObject(timer); timer = new System::Timer(); timer->onInterval.Connect(&Cursor::OnTimer, this); timer->Start(500); /* Redraw and show cursor. */ Paint(SP_PAINT); ShowCursor(True); return Success(); } S::Void S::GUI::Cursor::SetMaxSize(Int newMaxSize) { if (newMaxSize <= 0) maxSize = 32768; else maxSize = newMaxSize; } S::Void S::GUI::Cursor::SetIMEAdvance(Int newIMEAdvance) { ShowCursor(False); imeAdvance = newIMEAdvance; } S::Void S::GUI::Cursor::SetIMECursor(Bool newIMECursor) { ShowCursor(False); imeCursor = newIMECursor; } /* Returns the display cursor position * for a given logical cursor position. */ S::Int S::GUI::Cursor::GetDisplayCursorPositionFromLogical(Int promptPos) const { FriBidiStrIndex length = text.Length(); if (length == 0) return 0; String wText = text; Int wPromptPos = promptPos; if (Binary::IsFlagSet(GetFlags(), CF_MULTILINE)) { Int lineStart = promptPos; Int lineLength = 0; for (Int i = promptPos - 1; i >= 0; i--) { if (text[i] == '\n') break; lineStart--; } for (Int i = lineStart; i < length; i++) { if (text[i] == '\n' || text[i] == 0) break; lineLength++; } wText = text.SubString(lineStart, lineLength); wPromptPos = promptPos - lineStart; } return GetDisplayCursorPositionFromLogical(wText, wPromptPos); } /* Returns the display cursor position * for a given logical cursor position. */ S::Int S::GUI::Cursor::GetDisplayCursorPositionFromLogical(const String &line, Int promptPos) const { return GetDisplayCursorPositionFromVisual(line, GetVisualCursorPositionFromLogical(line, promptPos)); } /* Returns the display cursor position * for a given visual cursor position. */ S::Int S::GUI::Cursor::GetDisplayCursorPositionFromVisual(const String &line, Int promptPos) const { FriBidiStrIndex length = line.Length(); if (length == 0) return 0; Int position = 0; if (!Binary::IsFlagSet(container->GetFlags(), EDB_ASTERISK)) { String string = line; if (Setup::useIconv && ContainsRTLCharacters(line)) { FriBidiChar *visual = new FriBidiChar [length + 1]; FriBidiParType type = (IsRightToLeft() ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR); fribidi_log2vis((FriBidiChar *) string.ConvertTo("UCS-4LE"), length, &type, visual, NIL, NIL, NIL); visual[length] = 0; string.ImportFrom("UCS-4LE", (char *) visual); delete [] visual; } /* Convert tabs. */ Int offset = 0; for (Int i = 0; i < length; i++) { if (string[i] != '\t') continue; Int spaces = tabSize - i % tabSize; string = string.Head(i).Append(String().FillN(' ', spaces)).Append(string.Tail(length - i - 1)); length += spaces - 1; if (i < promptPos + offset) offset += spaces - 1; } if (!IsRightToLeft()) position += font.GetScaledTextSizeX(string.Head( promptPos + offset)) - visibleOffset; else position += font.GetScaledTextSizeX(string.Tail(length - promptPos - offset)) - visibleOffset; } else { position += font.GetScaledTextSizeX(String().FillN('*', promptPos)) - visibleOffset; } return position; } /* Return the logical cursor position * for a given display cursor position. */ S::Int S::GUI::Cursor::GetLogicalCursorPositionFromDisplay(const String &line, Int displayPos) const { FriBidiStrIndex length = line.Length(); if (length == 0) return 0; /* Find best position using binary search. */ Int bestPos = 0; Int bestValue = 2147483647; Int startPos = 0; Int endPos = length; while (endPos >= startPos) { /* Select element to compare and perform comparison. */ Int m = (startPos + endPos) / 2; Int pos = GetDisplayCursorPositionFromVisual(line, m); if ((!IsRightToLeft() && pos > displayPos) || ( IsRightToLeft() && pos < displayPos)) endPos = m - 1; else startPos = m + 1; if (Math::Abs(pos - displayPos) < bestValue) { bestPos = m; bestValue = Math::Abs(pos - displayPos); } } return GetLogicalCursorPositionFromVisual(line, bestPos); } /* Returns the cursor position in the visual string * for a given logical cursor position. */ S::Int S::GUI::Cursor::GetVisualCursorPositionFromLogical(const String &line, Int n) const { FriBidiStrIndex length = line.Length(); if (length == 0) return 0; Int position = n; /* Check if the input string contains RTL characters. */ if (Setup::useIconv && ContainsRTLCharacters(line)) { /* Get BiDi types for input string. */ FriBidiCharType *types = new FriBidiCharType [length + 1]; fribidi_get_bidi_types((FriBidiChar *) line.ConvertTo("UCS-4LE"), length, types); /* Get visual cursor position. */ FriBidiStrIndex *positions = new FriBidiStrIndex [length + 1]; FriBidiParType type = (IsRightToLeft() ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR); fribidi_log2vis((FriBidiChar *) line.ConvertTo("UCS-4LE"), length, &type, NIL, positions, NIL, NIL); if (n == length) { if ( FRIBIDI_IS_RTL(types[n - 1])) position = positions[n - 1]; else position = positions[n - 1] + 1; } else if (n == 0) { if ( FRIBIDI_IS_RTL(types[n ])) position = positions[n ] + 1; else position = positions[n ]; } else { if ( FRIBIDI_IS_RTL(types[n ])) position = positions[n ] + 1; else if ( FRIBIDI_IS_RTL(types[n - 1])) position = positions[n - 1]; else if ( FRIBIDI_IS_SPACE(types[n]) && !FRIBIDI_IS_RTL(types[n - 1])) position = positions[n - 1] + 1; else position = positions[n ]; } delete [] types; delete [] positions; } return position; } /* Returns the cursor position in the logical string * for a given visual cursor position. */ S::Int S::GUI::Cursor::GetLogicalCursorPositionFromVisual(const String &line, Int n) const { FriBidiStrIndex length = line.Length(); if (length == 0) return 0; Int position = n; /* Check if the input string contains RTL characters. */ if (Setup::useIconv && ContainsRTLCharacters(line)) { /* Get BiDi types for input string. */ FriBidiCharType *types = new FriBidiCharType [length + 1]; fribidi_get_bidi_types((FriBidiChar *) line.ConvertTo("UCS-4LE"), length, types); /* Get visual cursor position. */ FriBidiStrIndex *positions = new FriBidiStrIndex [length + 1]; FriBidiParType type = (IsRightToLeft() ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR); fribidi_log2vis((FriBidiChar *) line.ConvertTo("UCS-4LE"), length, &type, NIL, NIL, positions, NIL); if (n == length) { if ( FRIBIDI_IS_RTL(types[n - 1])) position = positions[n - 1]; else position = positions[n - 1] + 1; } else if (n == 0) { if ( FRIBIDI_IS_RTL(types[n ])) position = positions[n ] + 1; else position = positions[n ]; } else { if ( FRIBIDI_IS_RTL(types[n ])) position = positions[n ] + 1; else if ( FRIBIDI_IS_RTL(types[n - 1])) position = positions[n - 1]; else if ( FRIBIDI_IS_SPACE(types[n]) && !FRIBIDI_IS_RTL(types[n - 1])) position = positions[n - 1] + 1; else position = positions[n ]; } delete [] types; delete [] positions; } return position; } /* Convert tabs in a string. */ S::String S::GUI::Cursor::ConvertTabs(const String &line, Int tabSize) { String string = line; Int stringLength = string.Length(); for (Int i = 0; i < stringLength; i++) { if (string[i] != '\t') continue; Int spaces = tabSize - i % tabSize; string = string.Head(i).Append(String().FillN(' ', spaces)).Append(string.Tail(stringLength - i - 1)); stringLength += spaces - 1; } return string; } /* Check if the string contains right-to-left characters. */ S::Bool S::GUI::Cursor::ContainsRTLCharacters(const String &line) { FriBidiStrIndex length = line.Length(); if (length == 0) return False; Bool rtlCharacters = False; if (Setup::useIconv) { /* Get BiDi types for input string. */ FriBidiCharType *types = new FriBidiCharType [length + 1]; fribidi_get_bidi_types((FriBidiChar *) line.ConvertTo("UCS-4LE"), length, types); /* Check if the input string contains RTL characters. */ for (Int i = 0; i < length; i++) { if (FRIBIDI_IS_RTL(types[i])) { rtlCharacters = True; break; } } delete [] types; } else { for (Int i = 0; i < length; i++) { if (line[i] >= 0x0590 && line[i] <= 0x08FF) { rtlCharacters = True; break; } } } return rtlCharacters; } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/special/dragcontrol.cpp000077500000000000000000000030241516402577000263130ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2010 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::GUI::DragControl::classID = S::Object::RequestClassID(); S::GUI::DragControl::DragControl() : Widget(Point(), Size(4096, 4096)) { type = classID; orientation = OR_CENTER; dragHotspot = new Hotspot(GetPosition(), GetSize()); dragHotspot->onMouseDragStart.Connect(&DragControl::OnMouseDragStart, this); dragHotspot->onMouseDrag.Connect(&DragControl::OnMouseDrag, this); Add(dragHotspot); } S::GUI::DragControl::~DragControl() { DeleteObject(dragHotspot); } S::Void S::GUI::DragControl::OnMouseDragStart(const Point &mousePos) { startMousePos = mousePos; } S::Void S::GUI::DragControl::OnMouseDrag(const Point &mousePos) { Window *window = container->GetContainerWindow(); if (!window->IsMaximized()) window->SetPosition(window->GetPosition() - (Point((IsRightToLeft() ? window->GetWidth() - startMousePos.x : startMousePos.x), startMousePos.y) - Point((IsRightToLeft() ? window->GetWidth() - mousePos.x : mousePos.x), mousePos.y))); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/special/droparea.cpp000077500000000000000000000035261516402577000256010ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2017 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::GUI::DropArea::classID = S::Object::RequestClassID(); S::GUI::DropArea::DropArea(const Point &iPos, const Size &iSize) : Widget(iPos, iSize) { type = classID; dropTarget = True; orientation = OR_FREE; if (GetSize() == Size(0, 0)) SetSize(Size(4096, 4096)); onDropFile.SetParentObject(this); onDropFiles.SetParentObject(this); } S::GUI::DropArea::~DropArea() { } S::Int S::GUI::DropArea::Hide() { visible = False; return Success(); } S::Int S::GUI::DropArea::Process(Int message, Int wParam, Int lParam) { if (!IsRegistered()) return Error(); if (!IsActive() || !IsVisible()) return Success(); switch (message) { case SM_DROPFILES: { Point mousePos = Point(wParam, lParam); Point realPos = GetRealPosition(); Size realSize = GetRealSize(); if (mousePos.x > realPos.x && mousePos.x < (realPos.x + realSize.cx) && mousePos.y > realPos.y && mousePos.y < (realPos.y + realSize.cy)) { const Array &fileNames = GetContainerWindow()->GetDroppedFiles(); EnterProtectedRegion(); foreach (const String &fileName, fileNames) onDropFile.Emit(fileName); onDropFiles.Emit(fileNames); LeaveProtectedRegion(); return MessageProcessed; } } break; } return Widget::Process(message, wParam, lParam); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/special/shortcut.cpp000077500000000000000000000115411516402577000256530ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2017 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include const S::Short S::GUI::Shortcut::classID = S::Object::RequestClassID(); S::GUI::Shortcut::Shortcut(Int iFlags, Int iKey, Widget *iRef, Int iParam) : Widget(Point(), Size()) { type = classID; orientation = OR_FREE; key = iKey; flags = iFlags; param = iParam; ref = iRef; onKeyDown.SetParentObject(this); } S::GUI::Shortcut::~Shortcut() { } S::Int S::GUI::Shortcut::Process(Int message, Int wParam, Int lParam) { if (!IsRegistered()) return Error(); if (!IsActive()) return Success(); if (ref != NIL && !ref->IsActive()) return Success(); switch (message) { case SM_KEYDOWN: if (wParam == key) { if ((((flags & SC_ALT) && Input::Keyboard::GetKeyState(Input::Keyboard::KeyAlt)) || (!(flags & SC_ALT) && !Input::Keyboard::GetKeyState(Input::Keyboard::KeyAlt))) && (((flags & SC_CTRL) && Input::Keyboard::GetKeyState(Input::Keyboard::KeyControl)) || (!(flags & SC_CTRL) && !Input::Keyboard::GetKeyState(Input::Keyboard::KeyControl))) && (((flags & SC_CMD) && Input::Keyboard::GetKeyState(Input::Keyboard::KeyCommand)) || (!(flags & SC_CMD) && !Input::Keyboard::GetKeyState(Input::Keyboard::KeyCommand))) && (((flags & SC_SHIFT) && Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) || (!(flags & SC_SHIFT) && !Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)))) { onKeyDown.Emit(param); return MessageProcessed; } } break; } return Widget::Process(message, wParam, lParam); } S::Int S::GUI::Shortcut::SetShortcut(Int nFlags, Int nKey, Widget *nRef, Int nParam) { key = nKey; flags = nFlags; param = nParam; ref = nRef; return Success(); } S::String S::GUI::Shortcut::ToString() const { String keyString; if (key >= '0' && key <= '9') keyString[0] = key; else if (key >= 'A' && key <= 'Z') keyString[0] = key; if (key >= Input::Keyboard::KeyF1 && key <= Input::Keyboard::KeyF24) keyString = String("F").Append(String::FromInt(1 + (key - Input::Keyboard::KeyF1))); else if (key == Input::Keyboard::KeyBack) keyString = I18n::Translator::defaultTranslator->TranslateString("Backspace"); else if (key == Input::Keyboard::KeyTab) keyString = I18n::Translator::defaultTranslator->TranslateString("Tab"); else if (key == Input::Keyboard::KeyReturn) keyString = I18n::Translator::defaultTranslator->TranslateString("Return"); else if (key == Input::Keyboard::KeyEscape) keyString = I18n::Translator::defaultTranslator->TranslateString("Esc"); else if (key == Input::Keyboard::KeySpace) keyString = I18n::Translator::defaultTranslator->TranslateString("Space"); else if (key == Input::Keyboard::KeyPrior) keyString = I18n::Translator::defaultTranslator->TranslateString("PgUp"); else if (key == Input::Keyboard::KeyNext) keyString = I18n::Translator::defaultTranslator->TranslateString("PgDown"); else if (key == Input::Keyboard::KeyEnd) keyString = I18n::Translator::defaultTranslator->TranslateString("End"); else if (key == Input::Keyboard::KeyHome) keyString = I18n::Translator::defaultTranslator->TranslateString("Home"); else if (key == Input::Keyboard::KeyLeft) keyString = I18n::Translator::defaultTranslator->TranslateString("Left"); else if (key == Input::Keyboard::KeyUp) keyString = I18n::Translator::defaultTranslator->TranslateString("Up"); else if (key == Input::Keyboard::KeyRight) keyString = I18n::Translator::defaultTranslator->TranslateString("Right"); else if (key == Input::Keyboard::KeyDown) keyString = I18n::Translator::defaultTranslator->TranslateString("Down"); else if (key == Input::Keyboard::KeyInsert) keyString = I18n::Translator::defaultTranslator->TranslateString("Ins"); else if (key == Input::Keyboard::KeyDelete) keyString = I18n::Translator::defaultTranslator->TranslateString("Del"); return (Binary::IsFlagSet(flags, SC_CTRL) ? I18n::Translator::defaultTranslator->TranslateString("Ctrl").Append("+") : String()) .Append(Binary::IsFlagSet(flags, SC_CMD) ? I18n::Translator::defaultTranslator->TranslateString("Cmd").Append("+") : String()) .Append(Binary::IsFlagSet(flags, SC_ALT) ? I18n::Translator::defaultTranslator->TranslateString("Alt").Append("+") : String()) .Append(Binary::IsFlagSet(flags, SC_SHIFT) ? I18n::Translator::defaultTranslator->TranslateString("Shift").Append("+") : String()) .Append(keyString); } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/special/tooltip.cpp000077500000000000000000000107271516402577000254770ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include const S::Short S::GUI::Tooltip::classID = S::Object::RequestClassID(); S::GUI::Tooltip::Tooltip() : Widget(Point(), Size()) { type = classID; orientation = OR_FREE; toolWindow = NIL; timeOut = 5000; timer = NIL; layer = NIL; font.SetColor(Setup::TooltipTextColor); } S::GUI::Tooltip::~Tooltip() { if (timer != NIL) { timer->Stop(); DeleteObject(timer); } if (toolWindow != NIL) DeleteObject(toolWindow); } S::Int S::GUI::Tooltip::Show() { if (visible) return Success(); visible = True; if (!IsRegistered()) return Success(); Window *window = container->GetContainerWindow(); Surface *surface = GetDrawSurface(); Rect monitor = System::Screen::GetActiveScreenWorkArea(); Float scaleFactor = surface->GetSurfaceDPI() / 96.0; Size tSize = (layer != NIL ? layer->GetSize() : Size(font.GetUnscaledTextSizeX(text) + 6, font.GetUnscaledTextSizeY(text) + 4)); Size sSize = tSize * scaleFactor; Point tPos = Point(GetX(), GetY() - sSize.cy + 1); if (tPos.y + window->GetY() < monitor.top + 2) tPos.y = GetY() + monitor.top + 2 + Setup::HoverHeight; if (!IsRightToLeft()) { if (tPos.x + window->GetX() + sSize.cx > monitor.right - 2) tPos.x = -window->GetX() + monitor.right - 2 - sSize.cx; if (tPos.x + window->GetX() < monitor.left + 2) tPos.x = -window->GetX() + monitor.left + 2; } else { if (window->GetWidth() - tPos.x + window->GetX() > monitor.right - 2) tPos.x = -monitor.right + 2 + window->GetWidth() + window->GetX(); if (window->GetWidth() - tPos.x - sSize.cx + window->GetX() < monitor.left + 2) tPos.x = -(monitor.left + 2) + window->GetWidth() + window->GetX() - sSize.cx; } toolWindow = new ToolWindow(tPos, tSize); toolWindow->onPaint.Connect(&Tooltip::OnToolWindowPaint, this); toolWindow->onEvent.Connect(&Tooltip::OnToolWindowEvent, this); toolWindow->SetBackgroundColor(Setup::TooltipColor); if (layer != NIL) toolWindow->Add(layer); Add(toolWindow); if (timeOut != 0) { timer = new System::Timer(); timer->onInterval.Connect(&Tooltip::OnTimer, this); timer->Start(timeOut); } onShow.Emit(); return Success(); } S::Int S::GUI::Tooltip::Hide() { if (!visible) return Success(); visible = False; if (!IsRegistered()) return Success(); if (toolWindow != NIL) { toolWindow->Close(); Remove(toolWindow); if (layer != NIL) toolWindow->Remove(layer); toolWindow->onPaint.Disconnect(&Tooltip::OnToolWindowPaint, this); toolWindow->onEvent.Disconnect(&Tooltip::OnToolWindowEvent, this); DeleteObject(toolWindow); toolWindow = NIL; } onHide.Emit(); return Success(); } S::Void S::GUI::Tooltip::OnToolWindowPaint() { Surface *surface = toolWindow->GetDrawSurface(); Rect tRect = Rect(Point(0, 0), surface->GetSize()); surface->Box(tRect, Color(0, 0, 0), Rect::Outlined); surface->SetText(text, tRect + Point(2, 1), font); } S::Void S::GUI::Tooltip::OnToolWindowEvent(Int message, Int wParam, Int lParam) { static Bool forwarding = False; if (forwarding) return; Window *window = container ? container->GetContainerWindow() : NIL; if (window == NIL) return; forwarding = True; EnterProtectedRegion(); switch (message) { /* Forward mouse wheel messages posted to * the tool window to our parent window. */ case SM_MOUSEWHEEL: window->Process(message, wParam, lParam); break; /* Pass on keyboard events as well and hide * the tooltip immediately after char events. */ case SM_KEYDOWN: case SM_KEYUP: #ifdef __WIN32__ window->Process(message, wParam, lParam); #endif break; case SM_CHAR: #ifdef __WIN32__ window->Process(message, wParam, lParam); #endif Hide(); break; } LeaveProtectedRegion(); forwarding = False; } S::Void S::GUI::Tooltip::OnTimer() { Hide(); timer->Stop(); DeleteObject(timer); timer = NIL; } smooth-0.9.11~git20260403.0230c0da/classes/gui/widgets/widget.cpp000077500000000000000000000530561516402577000236520ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __WIN32__ # include # undef GetObject #endif const S::Short S::GUI::Widget::classID = S::Object::RequestClassID(); S::GUI::Widget::Widget(const Point &iPos, const Size &iSize) { type = classID; registered = False; container = NIL; visible = True; active = True; focussed = False; subtype = 0; pos = iPos; size = iSize; realPosValid = False; realSizeValid = False; orientation = OR_UPPERLEFT; text = NIL; unscaledTextSize= Size(); scaledTextSize = Size(); mouseOver = False; leftButtonDown = False; rightButtonDown = False; mouseDragging = False; alwaysActive = False; independent = False; tabstopCapable = False; dropTarget = False; tooltipText = NIL; tooltipLayer = NIL; tipTimer = NIL; tooltip = NIL; contextMenu = NIL; font.SetColor(Setup::TextColor); backgroundColor = Setup::BackgroundColor; backgroundColorSet = False; hitTest.Connect(&Widget::DefaultHitTest, this); getContextMenu.Connect((PopupMenu *) NIL); onShow.SetParentObject(this); onHide.SetParentObject(this); onChangePosition.SetParentObject(this); onChangeSize.SetParentObject(this); onMouseOver.SetParentObject(this); onMouseOut.SetParentObject(this); onLeftButtonDown.SetParentObject(this); onLeftButtonUp.SetParentObject(this); onLeftButtonClick.SetParentObject(this); onLeftButtonDoubleClick.SetParentObject(this); onRightButtonDown.SetParentObject(this); onRightButtonUp.SetParentObject(this); onRightButtonClick.SetParentObject(this); onRightButtonDoubleClick.SetParentObject(this); onMouseDragStart.SetParentObject(this); onMouseDrag.SetParentObject(this); onMouseDragEnd.SetParentObject(this); onMouseWheel.SetParentObject(this); onAction.SetParentObject(this); onOpenContextMenu.SetParentObject(this); onCloseContextMenu.SetParentObject(this); onGetFocus.SetParentObject(this); onLoseFocus.SetParentObject(this); onClickInFocus.SetParentObject(this); onRegister.SetParentObject(this); onUnregister.SetParentObject(this); } S::GUI::Widget::~Widget() { /* Clean up everything in case this widget * is not deleted using DeleteObject. */ DeactivateTooltip(); CloseContextMenu(); while (widgets.Length()) Remove(widgets.GetFirst()); widgets.RemoveAll(); if (registered && container != NIL) container->Remove(this); } S::Int S::GUI::Widget::EnableLocking(Bool enable) { if (enable) widgets.EnableLocking(); else widgets.DisableLocking(); foreach (Widget *widget, widgets) widget->EnableLocking(enable); return Object::EnableLocking(enable); } S::Void S::GUI::Widget::EnqueueForDeletion() { onEnqueueForDeletion.Emit(); DeactivateTooltip(); CloseContextMenu(); if (registered && container != NIL) container->Remove(this); } S::Int S::GUI::Widget::Add(Widget *widget) { if (widget == NIL) return Error(); if (!widget->IsRegistered()) { widgets.Add(widget, widget->GetHandle()); widget->EnableLocking(IsLockingEnabled()); widget->SetContainer(this); widget->SetRegisteredFlag(True); widget->onRegister.Emit(this); if (widget->visible) { widget->visible = False; widget->Show(); } return Success(); } return Error(); } S::Int S::GUI::Widget::Remove(Widget *widget) { if (widget == NIL) return Error(); if (widget->IsRegistered()) { if (widgets.Remove(widget->GetHandle()) == True) { widget->Hide(); widget->onUnregister.Emit(this); widget->SetRegisteredFlag(False); widget->SetContainer(NIL); widget->visible = True; return Success(); } } return Error(); } S::GUI::Window *S::GUI::Widget::GetContainerWindow() const { Widget *widget = const_cast(this); while (widget->GetObjectType() != Window::classID) { if (widget->GetContainer() == NIL) return NIL; widget = widget->GetContainer(); } return (Window *) widget; } S::GUI::Surface *S::GUI::Widget::GetDrawSurface() const { if (IsVisible()) return container->GetDrawSurface(); else return Surface::GetNullSurface(); } S::GUI::Widget *S::GUI::Widget::GetPreviousTabstopWidget(Int widgetHandle) const { Widget *lastTabstopObject = NIL; if (registered && widgetHandle != 0) lastTabstopObject = container->GetPreviousTabstopWidget(GetHandle()); foreach (Widget *widget, widgets) { if (widget->GetHandle() == widgetHandle) return lastTabstopObject; if (widget->IsTabstopCapable() && widget->IsActive()) lastTabstopObject = widget; else if (widget->GetPreviousTabstopWidget(0) != NIL) lastTabstopObject = widget->GetPreviousTabstopWidget(0); } if (widgetHandle == 0) return lastTabstopObject; return NIL; } S::GUI::Widget *S::GUI::Widget::GetNextTabstopWidget(Int widgetHandle) const { Bool found = False; if (widgetHandle == 0) found = True; foreach (Widget *widget, widgets) { if (widget->GetHandle() == widgetHandle) { found = True; continue; } if (found && widget->IsTabstopCapable() && widget->IsActive()) return widget; else if (found && widget->GetNextTabstopWidget(0) != NIL) return widget->GetNextTabstopWidget(0); } if (registered && widgetHandle != 0) return container->GetNextTabstopWidget(GetHandle()); return NIL; } S::Void S::GUI::Widget::ComputeTextSize() { scaledTextSize.cx = font.GetScaledTextSizeX(text); scaledTextSize.cy = font.GetScaledTextSizeY(text); Float dpi = Surface().GetSurfaceDPI(); if (Math::Abs(dpi - 96.0) < 0.1) unscaledTextSize = scaledTextSize; else unscaledTextSize = scaledTextSize * 96.0 / dpi; } S::Void S::GUI::Widget::InvalidateMetrics() { realPosValid = False; realSizeValid = False; foreach (Widget *widget, widgets) widget->InvalidateMetrics(); } S::GUI::Point S::GUI::Widget::GetRealPosition() const { if (!registered) return pos; if (realPosValid) return realPos; Surface *surface = GetDrawSurface(); Point containerPos = container->GetRealPosition(); Size containerSize = container->GetRealSize(); Point scaledPos = pos * surface->GetSurfaceDPI() / 96.0; realPos = containerPos + scaledPos; if (orientation == OR_UPPERRIGHT) { realPos.x = containerPos.x + containerSize.cx - scaledPos.x; } else if (orientation == OR_LOWERLEFT) { realPos.y = containerPos.y + containerSize.cy - scaledPos.y; } else if (orientation == OR_LOWERRIGHT) { realPos.x = containerPos.x + containerSize.cx - scaledPos.x; realPos.y = containerPos.y + containerSize.cy - scaledPos.y; } realPosValid = True; return realPos; } S::GUI::Size S::GUI::Widget::GetRealSize() const { if (!registered) return size; if (realSizeValid) return realSize; Surface *surface = GetDrawSurface(); realSize = size * surface->GetSurfaceDPI() / 96.0; realSizeValid = True; return realSize; } S::Int S::GUI::Widget::SetBackgroundColor(const Color &nColor) { if (backgroundColorSet && backgroundColor == nColor) return Success(); backgroundColor = nColor; backgroundColorSet = True; Paint(SP_PAINT); return Success(); } const S::GUI::Color &S::GUI::Widget::GetBackgroundColor() const { if (backgroundColorSet) return backgroundColor; else if (IsRegistered()) return container->GetBackgroundColor(); else return Setup::BackgroundColor; } S::Bool S::GUI::Widget::IsBackgroundColorSet() const { if (backgroundColorSet) return True; else if (IsRegistered()) return container->IsBackgroundColorSet(); else return False; } S::Int S::GUI::Widget::Show() { if (visible) return Success(); /* Show ourself. */ visible = True; if (!registered) return Success(); if (IsVisible()) Paint(SP_PAINT); /* Show child widgets. */ for (Int i = 0; i < GetNOfObjects(); i++) { Widget *object = GetNthObject(i); if (object == NIL || !object->IsVisible()) continue; visible = False; object->Hide(); visible = True; object->Show(); } /* Notify listeners. */ onShow.Emit(); return Success(); } S::Int S::GUI::Widget::Hide() { if (!visible) return Success(); /* Hide child widgets. */ for (Int i = 0; i < GetNOfObjects(); i++) { Widget *object = GetNthObject(i); if (object == NIL || !object->IsVisible()) continue; object->Hide(); visible = False; object->Show(); visible = True; } /* Hide ourself. */ Surface *surface = (IsVisible() ? GetDrawSurface() : NIL); visible = False; if (!registered) return Success(); if (surface) { if (focussed) { focussed = False; onLoseFocus.Emit(); } surface->Box(GetVisibleArea(), container->GetBackgroundColor(), Rect::Filled); DeactivateTooltip(); } /* Reset mouse status. */ mouseOver = False; leftButtonDown = False; rightButtonDown = False; mouseDragging = False; /* Notify listeners. */ onHide.Emit(); return Success(); } S::Int S::GUI::Widget::Activate() { if (active) return Success(); Surface *surface = (IsVisible() ? GetDrawSurface() : NIL); if (surface) { surface->StartPaint(GetVisibleArea()); Hide(); } active = True; if (surface) { Show(); Process(SM_MOUSEMOVE, 0, 0); surface->EndPaint(); } onActivate.Emit(); return Success(); } S::Int S::GUI::Widget::Deactivate() { if (!active) return Success(); Surface *surface = (IsVisible() ? GetDrawSurface() : NIL); if (surface) { surface->StartPaint(GetVisibleArea()); Hide(); } active = False; foreach (Widget *widget, widgets) { widget->mouseOver = False; widget->leftButtonDown = False; widget->rightButtonDown = False; widget->mouseDragging = False; } if (surface) { Show(); surface->EndPaint(); } onDeactivate.Emit(); return Success(); } S::Int S::GUI::Widget::Paint(Int message) { if (!registered) return Error(); if (!visible) return Success(); Window *window = container->GetContainerWindow(); if (window == NIL) return Success(); switch (message) { case SP_PAINT: widgets.LockForRead(); foreach (Widget *widget, widgets) { if (widget->IsAffected(window->GetUpdateRect())) widget->Paint(message); } widgets.Unlock(); break; } return Success(); } S::Int S::GUI::Widget::Process(Int message, Int wParam, Int lParam) { if (!IsRegistered()) return Error(); if (!IsVisible()) return Success(); Window *window = container->GetContainerWindow(); if (window == NIL) return Success(); widgets.LockForWrite(); foreach (Widget *widget, widgets) { if (widget->Process(message, wParam, lParam) == MessageProcessed) { widgets.Unlock(); return MessageProcessed; } } widgets.Unlock(); if (!IsVisible()) return Success(); if (!IsActive()) return Success(); EnterProtectedRegion(); Int returnValue = Success(); Point mousePos = window->GetMousePosition(); switch (message) { case SM_MOUSEMOVE: { Point realPosition = GetRealPosition(); Rect visibleArea = GetVisibleArea(); if (!mouseOver && window->IsMouseOn(visibleArea) && hitTest.Call(mousePos - realPosition)) { mouseOver = True; if (statusText != NIL) window->SetStatusText(statusText); if ((tooltipText != NIL || tooltipLayer != NIL) && window->IsFocussed()) { Application::Lock lock; tipPos = mousePos; tipTimer = new System::Timer(); tipTimer->onInterval.Connect(&Widget::ActivateTooltip, this); tipTimer->Start(Setup::HoverTime); } Paint(SP_MOUSEIN); onMouseOver.Emit(); } else if (mouseOver && !(window->IsMouseOn(visibleArea) && hitTest.Call(mousePos - realPosition))) { mouseOver = False; leftButtonDown = False; rightButtonDown = False; if (statusText != NIL && window->GetStatusText() == statusText) window->RestoreDefaultStatusText(); DeactivateTooltip(); Paint(SP_MOUSEOUT); onMouseOut.Emit(); } else if (mouseOver && window->IsMouseOn(visibleArea) && hitTest.Call(mousePos - realPosition)) { Application::Lock lock; if (tipTimer != NIL && wParam == 0 && (Math::Abs(tipPos.x - mousePos.x) > Setup::HoverWidth / 2 || Math::Abs(tipPos.y - mousePos.y) > Setup::HoverHeight / 2)) { tipPos = mousePos; tipTimer->Stop(); tipTimer->Start(Setup::HoverTime); } } } if (mouseDragging) { onMouseDrag.Emit(mousePos); } break; case SM_LBUTTONDOWN: if (mouseOver) { leftButtonDown = True; DeactivateTooltip(); Paint(SP_MOUSEDOWN); if (!focussed) { focussed = True; onGetFocus.Emit(); } else { onClickInFocus.Emit(); } onLeftButtonDown.Emit(mousePos); if (!mouseDragging) { mouseDragging = True; onMouseDragStart.Emit(mousePos); } } else { if (focussed) { focussed = False; onLoseFocus.Emit(); } } break; case SM_LBUTTONDBLCLK: if (mouseOver) { leftButtonDown = True; Paint(SP_MOUSEDOWN); onLeftButtonDown.Emit(mousePos); onLeftButtonDoubleClick.Emit(mousePos); } break; case SM_LBUTTONUP: if (mouseOver) { Paint(SP_MOUSEUP); onLeftButtonUp.Emit(mousePos); if (leftButtonDown) { leftButtonDown = False; onLeftButtonClick.Emit(mousePos); } } if (mouseDragging) { mouseDragging = False; onMouseDragEnd.Emit(mousePos); } break; case SM_RBUTTONDOWN: case SM_RBUTTONDBLCLK: if (mouseOver) { OpenContextMenu(); /* Force mouseOut event. */ window->Process(SM_MOUSEMOVE, 0, 0); } break; case SM_MOUSEWHEEL: { UnsignedInt scrollLines = 0; #ifdef __WIN32__ SystemParametersInfo(104, NIL, &scrollLines, NIL); #endif if (scrollLines <= 0) scrollLines = 3; onMouseWheel.Emit(Float(wParam) / 120.0 * scrollLines); } break; case SM_KEYDOWN: if (!focussed || !tabstopCapable) break; if (wParam == Input::Keyboard::KeyTab) { Widget *widget = NIL; if (Input::Keyboard::GetKeyState(Input::Keyboard::KeyShift)) widget = container->GetPreviousTabstopWidget(GetHandle()); else widget = container->GetNextTabstopWidget(GetHandle()); if (widget != NIL) { focussed = False; onLoseFocus.Emit(); widget->SetFocusByKeyboard(); } returnValue = MessageProcessed; } break; case SM_LOSEFOCUS: if (focussed) { Window *focusWnd = (Window *) Object::GetObject(wParam, Window::classID); if (focusWnd != NIL) { if ((focusWnd->GetObjectType() == ToolWindow::classID && focusWnd->GetOrder() >= window->GetOrder()) || focusWnd == window) break; } focussed = False; onLoseFocus.Emit(); } break; } LeaveProtectedRegion(); return returnValue; } S::Void S::GUI::Widget::ActivateTooltip() { Application::Lock lock; if (tipTimer == NIL || tooltip != NIL) return; tipTimer->Stop(); DeleteObject(tipTimer); tipTimer = NIL; if (IsVisible()) { Window *window = container->GetContainerWindow(); tooltip = new Tooltip(); if (tooltipText != NIL) { tooltip->SetText(tooltipText); tooltip->SetMetrics(window->GetMousePosition() - Point(tooltip->GetUnscaledTextWidth() > 0 ? Math::Round(0.2 * tooltip->GetUnscaledTextWidth()) : 20, Setup::HoverHeight / 2 + 1), Size(0, 0)); tooltip->SetTimeout(3000); } else if (tooltipLayer != NIL) { tooltipLayer->Show(); tooltip->SetLayer(tooltipLayer); tooltip->SetPosition(window->GetMousePosition() - Point(Math::Round(0.2 * tooltipLayer->GetWidth()), Setup::HoverHeight / 2 + 1)); tooltip->SetTimeout(3000); } PopupMenu::internalOnOpenPopupMenu.Connect(&Widget::DeactivateTooltip, this); window->Add(tooltip); } } S::Void S::GUI::Widget::DeactivateTooltip() { Application::Lock lock; if (tipTimer != NIL) { tipTimer->Stop(); DeleteObject(tipTimer); tipTimer = NIL; } if (tooltip != NIL) { PopupMenu::internalOnOpenPopupMenu.Disconnect(&Widget::DeactivateTooltip, this); tooltip->Hide(); DeleteObject(tooltip); tooltip = NIL; } } S::Void S::GUI::Widget::OpenContextMenu() { if (contextMenu != NIL) CloseContextMenu(); contextMenu = getContextMenu.Call(); if (contextMenu != NIL) { onOpenContextMenu.Emit(); Window *window = container->GetContainerWindow(); Surface *surface = GetDrawSurface(); Rect monitor = System::Screen::GetActiveScreenWorkArea(); Float scaleFactor = surface->GetSurfaceDPI() / 96.0; contextMenu->CalculateSize(); Point popupPos = window->GetMousePosition(); Size popupSize = contextMenu->GetSize(); if (!IsRightToLeft()) { if (window->GetX() + popupPos.x + Math::Round(popupSize.cx * scaleFactor) >= monitor.right) popupPos.x = popupPos.x - Math::Round(popupSize.cx * scaleFactor); } else { if (window->GetX() + (window->GetWidth() - popupPos.x) - Math::Round(popupSize.cx * scaleFactor) < monitor.left) popupPos.x = popupPos.x - Math::Round(popupSize.cx * scaleFactor); } if (window->GetY() + popupPos.y + Math::Round(popupSize.cy * scaleFactor) >= monitor.bottom) popupPos.y = popupPos.y - Math::Round(popupSize.cy * scaleFactor); contextMenu->SetPosition(popupPos); contextMenu->SetAlwaysActive(True); contextMenu->internalRequestClose.Connect(&Widget::CloseContextMenu, this); Add(contextMenu); } } S::Void S::GUI::Widget::CloseContextMenu() { if (contextMenu != NIL) { contextMenu->internalRequestClose.Disconnect(&Widget::CloseContextMenu, this); Remove(contextMenu); contextMenu = NIL; onCloseContextMenu.Emit(); } } S::Bool S::GUI::Widget::IsDropTarget() const { if (dropTarget) return True; foreach (Widget *widget, widgets) { if (widget->IsDropTarget()) return True; } return False; } S::Int S::GUI::Widget::SetFocus() { if (!focussed) { focussed = True; onGetFocus.Emit(); if (GetNOfObjects() > 0) GetNthObject(0)->SetFocus(); } return Success(); } S::Void S::GUI::Widget::SetFocusByKeyboard() { if (!focussed) { focussed = True; onGetFocus.Emit(); onGetFocusByKeyboard.Emit(); } } S::Int S::GUI::Widget::SetText(const String &nText) { if (text == nText) return Success(); Surface *surface = GetDrawSurface(); Bool prevVisible = IsVisible(); Bool prevFocussed = focussed; if (registered && prevFocussed) { focussed = False; } if (registered && prevVisible) { surface->StartPaint(GetVisibleArea()); Hide(); } text = nText; ComputeTextSize(); if (registered && prevVisible) { Show(); Process(SM_MOUSEMOVE, 0, 0); surface->EndPaint(); } if (registered && prevFocussed) { focussed = True; } return Success(); } S::Int S::GUI::Widget::SetTooltipText(const String &nTooltipText) { tooltipText = nTooltipText; tooltipLayer = NIL; return Success(); } S::Int S::GUI::Widget::SetTooltipLayer(Layer *nTooltipLayer) { tooltipText = NIL; tooltipLayer = nTooltipLayer; return Success(); } S::Int S::GUI::Widget::SetFont(const Font &nFont) { if (font == nFont) return Success(); Surface *surface = GetDrawSurface(); Bool prevVisible = IsVisible(); Bool prevFocussed = focussed; if (registered && prevFocussed) { focussed = False; } if (registered && prevVisible) { surface->StartPaint(GetVisibleArea()); Hide(); } font = nFont; ComputeTextSize(); if (registered && prevVisible) { Show(); Process(SM_MOUSEMOVE, 0, 0); surface->EndPaint(); } if (registered && prevFocussed) { focussed = True; } return Success(); } S::Int S::GUI::Widget::SetOrientation(Int nOrientation) { if (orientation == nOrientation) return Success(); Bool prevVisible = IsVisible(); if (registered && prevVisible) Hide(); orientation = nOrientation; if (registered && prevVisible) Show(); return Success(); } S::GUI::Rect S::GUI::Widget::GetVisibleArea() const { if (!IsRegistered()) return Rect(); if (IsIndependent()) return Rect(GetRealPosition(), GetRealSize()); else return Rect::OverlapRect(Rect(GetRealPosition(), GetRealSize()), container->GetVisibleArea()); } S::Int S::GUI::Widget::SetMetrics(const Point &nPos, const Size &nSize) { if (nPos.x == pos.x && nPos.y == pos.y && nSize.cx == size.cx && nSize.cy == size.cy) return Success(); DeactivateTooltip(); Surface *surface = (IsVisible() ? GetDrawSurface() : NIL); if (surface && orientation != OR_FREE) surface->StartPaint(container->GetVisibleArea()); if (surface ) Hide(); InvalidateMetrics(); if (nPos.x != pos.x || nPos.y != pos.y ) { pos = nPos; onChangePosition.Emit(pos); } if (nSize.cx != size.cx || nSize.cy != size.cy) { size = nSize; onChangeSize.Emit(size); } if (surface ) { Show(); Process(SM_MOUSEMOVE, 0, 0); } if (surface && orientation != OR_FREE) surface->EndPaint(); return Success(); } S::Bool S::GUI::Widget::IsRightToLeft() const { if (IsRegistered()) { Window *containerWindow = container->GetContainerWindow(); if (containerWindow != NIL) return containerWindow->IsRightToLeft(); } return Setup::rightToLeft; } S::Bool S::GUI::Widget::IsAffected(const Rect &uRect) const { return Rect::DoRectsOverlap(uRect, Rect(GetRealPosition() - Point(10, 10), GetRealSize() + Size(20, 20))); } S::Bool S::GUI::Widget::DefaultHitTest(const Point &mousePos) { Size realSize = GetRealSize(); return (mousePos.x >= 0 && mousePos.y >= 0 && mousePos.x <= realSize.cx - 1 && mousePos.y <= realSize.cy - 1); } smooth-0.9.11~git20260403.0230c0da/classes/gui/window/000077500000000000000000000000001516402577000215105ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/window/Makefile000066400000000000000000000006671516402577000231610ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = toolwindow.o window.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,backends) CLEANCMD1 = $(call cleanin,backends) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/000077500000000000000000000000001516402577000232625ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/Makefile000066400000000000000000000011611516402577000247210ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. # Enter object files here: OBJECTS = windowbackend.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,cocoa) ALLCMD2 = $(call makein,gdi) ALLCMD3 = $(call makein,haiku) ALLCMD4 = $(call makein,xlib) CLEANCMD1 = $(call cleanin,cocoa) CLEANCMD2 = $(call cleanin,gdi) CLEANCMD3 = $(call cleanin,haiku) CLEANCMD4 = $(call cleanin,xlib) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/cocoa/000077500000000000000000000000001516402577000243465ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/cocoa/Makefile000066400000000000000000000006541516402577000260130ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_OSX),True) OBJECTS += windowcocoa.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/cocoa/windowcocoa.mm000066400000000000000000001403111516402577000272150ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2025 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include using namespace smooth; using namespace smooth::GUI; S::GUI::WindowBackend *CreateWindowCocoa() { return new S::GUI::WindowCocoa(); } S::Int windowCocoaTmp = S::GUI::WindowBackend::SetBackend(&CreateWindowCocoa); S::Int addWindowCocoaInitTmp = S::AddInitFunction(&S::GUI::WindowCocoa::Initialize); S::Int addWindowCocoaFreeTmp = S::AddFreeFunction(&S::GUI::WindowCocoa::Free); S::Array S::GUI::WindowCocoa::windowBackends; const int NSApplicationPaint = 1; const int NSApplicationMap = 2; const int NSApplicationUnmap = 3; const int NSApplicationMove = 4; const int NSApplicationResize = 5; const int NSApplicationFocus = 6; const int NSApplicationUnfocus = 7; const int NSApplicationInsertText = 8; const int NSApplicationDropFiles = 9; @interface CocoaView : NSView { @private NSTrackingArea *trackingArea; NSMutableAttributedString *editString; NSRange markedRange; NSMutableDictionary *markedAttributes; GUI::Cursor *cursor; GUI::Point cursorPosition; } /* NSView methods. */ - (id) initWithFrame: (NSRect) frameRect; - (void) updateTrackingAreas; - (void) handleEvent: (NSEvent *) event; - (void) mouseMoved: (NSEvent *) event; - (void) mouseEntered: (NSEvent *) event; - (void) mouseExited: (NSEvent *) event; - (void) mouseDown: (NSEvent *) event; - (void) mouseDragged: (NSEvent *) event; - (void) mouseUp: (NSEvent *) event; - (void) rightMouseDown: (NSEvent *) event; - (void) rightMouseDragged: (NSEvent *) event; - (void) rightMouseUp: (NSEvent *) event; - (void) otherMouseDown: (NSEvent *) event; - (void) otherMouseDragged: (NSEvent *) event; - (void) otherMouseUp: (NSEvent *) event; - (void) scrollWheel: (NSEvent *) event; - (void) keyDown: (NSEvent *) event; - (void) keyUp: (NSEvent *) event; - (void) flagsChanged: (NSEvent *) event; - (BOOL) isFlipped; - (void) drawRect: (NSRect) rect; - (void) setFrameSize: (NSSize) newSize; - (BOOL) acceptsFirstResponder; /* NSTextInputClient methods. */ - (void) insertText: (id) string; - (void) insertText: (id) string replacementRange: (NSRange) replacementRange; - (void) setMarkedText: (id) string selectedRange: (NSRange) selectedRange replacementRange: (NSRange) replacementRange; - (BOOL) hasMarkedText; - (void) unmarkText; - (NSRange) selectedRange; - (NSRange) markedRange; - (NSArray *) validAttributesForMarkedText; - (NSUInteger) characterIndexForPoint: (NSPoint) aPoint; - (NSRect) firstRectForCharacterRange: (NSRange) aRange actualRange: (NSRangePointer) actualRange; - (NSAttributedString *) attributedSubstringForProposedRange: (NSRange) aRange actualRange: (NSRangePointer) actualRange; - (void) doCommandBySelector: (SEL) aSelector; /* Helper methods. */ - (void) setCursor: (GUI::Cursor *) aCursor position: (const GUI::Point &) aPoint; - (void) removeCursor: (GUI::Cursor *) aCursor; @end @implementation CocoaView /* NSView methods. */ - (id) initWithFrame: (NSRect) frameRect { [super initWithFrame: frameRect]; cursor = NIL; editString = [[[NSMutableAttributedString alloc] initWithString: @""] autorelease]; markedRange = NSMakeRange(NSNotFound, 0); markedAttributes = [[[NSMutableDictionary alloc] init] autorelease]; trackingArea = [[[NSTrackingArea alloc] initWithRect: [self visibleRect] options: NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways owner: self userInfo: nil] autorelease]; [self addTrackingArea: trackingArea]; return self; } - (void) updateTrackingAreas { [self removeTrackingArea: trackingArea]; trackingArea = [[[NSTrackingArea alloc] initWithRect: [self visibleRect] options: NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways owner: self userInfo: nil] autorelease]; [self addTrackingArea: trackingArea]; } - (void) handleEvent: (NSEvent *) event { WindowCocoa *backend = WindowCocoa::GetWindowBackend([event window]); if (backend != NIL) backend->ProcessSystemMessages(event); } - (void) mouseMoved: (NSEvent *) event { [self handleEvent: event]; } - (void) mouseEntered: (NSEvent *) event { [self handleEvent: event]; } - (void) mouseExited: (NSEvent *) event { [self handleEvent: event]; } - (void) mouseDown: (NSEvent *) event { [self handleEvent: event]; } - (void) mouseDragged: (NSEvent *) event { [self handleEvent: event]; } - (void) mouseUp: (NSEvent *) event { [self handleEvent: event]; } - (void) rightMouseDown: (NSEvent *) event { [self handleEvent: event]; } - (void) rightMouseDragged: (NSEvent *) event { [self handleEvent: event]; } - (void) rightMouseUp: (NSEvent *) event { [self handleEvent: event]; } - (void) otherMouseDown: (NSEvent *) event { [self handleEvent: event]; } - (void) otherMouseDragged: (NSEvent *) event { [self handleEvent: event]; } - (void) otherMouseUp: (NSEvent *) event { [self handleEvent: event]; } - (void) scrollWheel: (NSEvent *) event { [self handleEvent: event]; } - (void) keyDown: (NSEvent *) event { /* Collect queued key down events to process them all together. */ NSMutableArray *keyEvents = [NSMutableArray arrayWithCapacity: 1]; while (event != nil) { if (![self hasMarkedText]) [self handleEvent: event]; /* Check if event is relevant for us. */ NSString *characters = [event charactersIgnoringModifiers]; S::Int keySym = [characters length] >= 1 ? [characters characterAtIndex: 0] : 0; S::Int modifierFlags = [event modifierFlags]; if ([self hasMarkedText] || (keySym != NSTabCharacter && keySym != NSBackTabCharacter && keySym != NSDeleteCharacter && keySym != NSEnterCharacter && keySym != NSNewlineCharacter && keySym != NSCarriageReturnCharacter && keySym != NSHomeFunctionKey && keySym != NSEndFunctionKey && keySym != NSDeleteFunctionKey && keySym != NSLeftArrowFunctionKey && keySym != NSUpArrowFunctionKey && keySym != NSRightArrowFunctionKey && keySym != NSDownArrowFunctionKey && !(modifierFlags & NSControlKeyMask) && !(modifierFlags & NSCommandKeyMask))) [keyEvents addObject: event]; /* Get next key down event. */ event = [[self window] nextEventMatchingMask: NSKeyDownMask untilDate: [NSDate distantPast] inMode: NSDefaultRunLoopMode dequeue: YES]; } /* Send events to input manager. */ if ([keyEvents count] == 0) return; WindowCocoa *backend = WindowCocoa::GetWindowBackend([self window]); if (backend != NIL && cursor != NIL) { Surface *surface = cursor->GetDrawSurface(); surface->StartPaint(GUI::Rect(cursor->GetContainer()->GetRealPosition(), cursor->GetContainer()->GetRealSize())); [self interpretKeyEvents: keyEvents]; surface->EndPaint(); } } - (void) keyUp: (NSEvent *) event { [self handleEvent: event]; } - (void) flagsChanged: (NSEvent *) event { [self handleEvent: event]; } - (BOOL) isFlipped { return YES; } - (void) drawRect: (NSRect) rect { WindowCocoa *backend = WindowCocoa::GetWindowBackend([self window]); NSEvent *event = [NSEvent otherEventWithType: NSApplicationDefined location: NSMakePoint(0, 0) modifierFlags: 0 timestamp: 0 windowNumber: [[self window] windowNumber] context: nil subtype: NSApplicationPaint data1: (NSInteger) &rect data2: 0]; if (backend != NIL) backend->ProcessSystemMessages(event); if (markedRange.location != NSNotFound && cursor != NIL) { [[NSGraphicsContext currentContext] setShouldAntialias: YES]; [NSGraphicsContext saveGraphicsState]; GUI::Point realPos = cursor->GetRealPosition(); GUI::Size realSize = cursor->GetRealSize(); NSRectClip(NSMakeRect(realPos.x, realPos.y, realSize.cx, realSize.cy)); NSAttributedString *range = [editString attributedSubstringFromRange: markedRange]; [range drawAtPoint: NSMakePoint(cursorPosition.x - 1, cursorPosition.y - 2)]; [NSGraphicsContext restoreGraphicsState]; } } - (void) setFrameSize: (NSSize) newSize { [super setFrameSize: newSize]; WindowCocoa *backend = WindowCocoa::GetWindowBackend([self window]); NSEvent *event = [NSEvent otherEventWithType: NSApplicationDefined location: NSMakePoint(0, 0) modifierFlags: 0 timestamp: 0 windowNumber: [[self window] windowNumber] context: nil subtype: NSApplicationResize data1: 0 data2: 0]; if (backend != NIL) backend->ProcessSystemMessages(event); } - (BOOL) acceptsFirstResponder { return YES; } /* NSTextInputClient methods. */ - (void) insertText: (id) string { WindowCocoa *backend = WindowCocoa::GetWindowBackend([self window]); NSEvent *event = [NSEvent otherEventWithType: NSApplicationDefined location: NSMakePoint(0, 0) modifierFlags: 0 timestamp: 0 windowNumber: [[self window] windowNumber] context: nil subtype: NSApplicationInsertText data1: (NSInteger) string data2: 0]; if (backend != NIL && cursor != NIL) backend->ProcessSystemMessages(event); [self unmarkText]; } - (void) insertText: (id) string replacementRange: (NSRange) replacementRange { [self insertText: string]; } - (void) setMarkedText: (id) string selectedRange: (NSRange) selectedRange replacementRange: (NSRange) replacementRange { if (replacementRange.location == NSNotFound) replacementRange = NSMakeRange(0, 0); [editString beginEditing]; if ([string length] == 0) { [self unmarkText]; } else { markedRange = NSMakeRange(replacementRange.location, [string length]); if ([string isKindOfClass: [NSAttributedString class]]) [editString replaceCharactersInRange: replacementRange withAttributedString: string]; else [editString replaceCharactersInRange: replacementRange withString: string]; [editString addAttributes: markedAttributes range: markedRange]; if (cursor != NIL) { S::String string; string.ImportFrom("UTF-8", [[[editString attributedSubstringFromRange: markedRange] string] UTF8String]); cursor->SetIMEAdvance(cursor->GetFont().GetScaledTextSizeX(string)); } } [editString endEditing]; [self setNeedsDisplay: YES]; } - (BOOL) hasMarkedText { return (markedRange.location == NSNotFound ? NO : YES); } - (void) unmarkText { markedRange = NSMakeRange(NSNotFound, 0); [editString setAttributedString: [[[NSAttributedString alloc] initWithString: @""] autorelease]]; [[NSInputManager currentInputManager] markedTextAbandoned: self]; if (cursor != NIL) cursor->SetIMEAdvance(0); } - (NSRange) selectedRange { return NSMakeRange(NSNotFound, 0); } - (NSRange) markedRange { return markedRange; } - (NSArray *) validAttributesForMarkedText { return [NSArray arrayWithObjects: NSMarkedClauseSegmentAttributeName, NSGlyphInfoAttributeName, nil]; } - (NSUInteger) characterIndexForPoint: (NSPoint) aPoint { return 0; } - (NSRect) firstRectForCharacterRange: (NSRange) aRange actualRange: (NSRangePointer) actualRange { if (actualRange) *actualRange = aRange; NSRect rect = NSMakeRect(0, 0, 0, 0); if (cursor != NIL) rect = NSMakeRect(cursorPosition.x, cursorPosition.y + cursor->GetFont().GetScaledTextSizeY(), 0, 0); rect = [self convertRectToBase: rect]; rect.origin = [[self window] convertBaseToScreen: rect.origin]; return rect; } - (NSAttributedString *) attributedSubstringForProposedRange: (NSRange) aRange actualRange: (NSRangePointer) actualRange { if (actualRange) *actualRange = aRange; return [editString attributedSubstringFromRange: aRange]; } - (void) doCommandBySelector: (SEL) aSelector { [super doCommandBySelector: aSelector]; } /* Helper methods. */ - (void) setCursor: (GUI::Cursor *) aCursor position: (const GUI::Point &) aPoint { const Font &font = aCursor->GetFont(); const Color color = font.GetColor(); const NSColor *nsColor = [NSColor colorWithCalibratedRed: color.GetRed() / 255.0 green: color.GetGreen() / 255.0 blue: color.GetBlue() / 255.0 alpha: 1.0]; [markedAttributes setObject: FontCocoa::GetNativeFont(font) forKey: NSFontAttributeName]; [markedAttributes setObject: nsColor forKey: NSForegroundColorAttributeName]; [self unmarkText]; [self setNeedsDisplay: YES]; cursor = aCursor; cursorPosition = aPoint; } - (void) removeCursor: (GUI::Cursor *) aCursor { if (cursor != aCursor) return; [self unmarkText]; [self setNeedsDisplay: YES]; cursor = NIL; } @end @interface CocoaWindow : NSWindow { @private NSUInteger styleMask; NSRect frameRect; NSRect contentRect; NSSize minSize; NSSize maxSize; BOOL zooming; } /* NSObject methods. */ - (void) performSelectorOnMainThread: (SEL) selector withObject:(id) arg waitUntilDone: (BOOL) wait; /* NSWindow methods. */ - (BOOL) worksWhenModal; - (void) orderFront: (id) sender; - (void) orderOut: (id) sender; - (void) makeKeyAndOrderFront: (id) sender; - (void) zoom: (id) sender; - (void) close; /* Helper Methods. */ - (id) initWithContentRect: (NSRect) rect styleMask: (NSUInteger) style; - (void) setFrame: (NSRect) rect; - (void) setMinSize: (NSSize) size; - (void) setMaxSize: (NSSize) size; - (BOOL) isZooming; - (void) setZooming: (BOOL) value; - (void) processEvent: (int) type; - (void) processEvent: (int) type withData: (NSInteger) data; - (NSDragOperation) draggingEntered: (id) sender; - (BOOL) performDragOperation: (id) sender; /* Internal use only. */ - (id) internalInitWithAttributes; - (void) internalSetFrameWithAttributes; - (void) internalSetMinSizeWithAttributes; - (void) internalSetMaxSizeWithAttributes; @end @implementation CocoaWindow /* NSObject methods. */ - (void) performSelectorOnMainThread: (SEL) selector withObject:(id) arg waitUntilDone: (BOOL) wait { /* If we shall wait for the call to complete, * we need to suspend our application lock. */ int suspendCount = (wait ? Application::Lock::SuspendLock() : 0); [super performSelectorOnMainThread: selector withObject: arg waitUntilDone: wait]; /* Resume the application lock. */ Application::Lock::ResumeLock(suspendCount); } /* NSWindow methods. */ - (BOOL) worksWhenModal { return YES; } - (void) orderFront: (id) sender { [super orderFront: sender]; [self processEvent: NSApplicationMap]; } - (void) orderOut: (id) sender { [super orderOut: sender]; [self processEvent: NSApplicationUnmap]; } - (void) makeKeyAndOrderFront: (id) sender { [super makeKeyAndOrderFront: sender]; [self processEvent: NSApplicationMap]; } - (void) zoom: (id) sender { if (![self isZoomed]) zooming = YES; [super zoom: sender]; } - (void) close { WindowCocoa *backend = WindowCocoa::GetWindowBackend(self); if (backend != NIL) backend->Close(); [super close]; } /* Helper Methods. */ - (id) initWithContentRect: (NSRect) rect styleMask: (NSUInteger) style { contentRect = rect; styleMask = style; zooming = NO; if ([NSThread isMainThread]) [self internalInitWithAttributes]; else [self performSelectorOnMainThread: @selector(internalInitWithAttributes) withObject: NIL waitUntilDone: YES]; return self; } - (void) setFrame: (NSRect) rect { frameRect = rect; if ([NSThread isMainThread]) [self internalSetFrameWithAttributes]; else [self performSelectorOnMainThread: @selector(internalSetFrameWithAttributes) withObject: NIL waitUntilDone: YES]; } - (void) setMinSize: (NSSize) size { minSize = size; if ([NSThread isMainThread]) [self internalSetMinSizeWithAttributes]; else [self performSelectorOnMainThread: @selector(internalSetMinSizeWithAttributes) withObject: NIL waitUntilDone: YES]; } - (void) setMaxSize: (NSSize) size { maxSize = size; if ([NSThread isMainThread]) [self internalSetMaxSizeWithAttributes]; else [self performSelectorOnMainThread: @selector(internalSetMaxSizeWithAttributes) withObject: NIL waitUntilDone: YES]; } - (BOOL) isZooming { return zooming; } - (void) setZooming: (BOOL) value { zooming = value; } - (void) processEvent: (int) type { [self processEvent: type withData: 0]; } - (void) processEvent: (int) type withData: (NSInteger) data { WindowCocoa *backend = WindowCocoa::GetWindowBackend(self); NSEvent *event = [NSEvent otherEventWithType: NSApplicationDefined location: NSMakePoint(0, 0) modifierFlags: 0 timestamp: 0 windowNumber: [self windowNumber] context: nil subtype: type data1: data data2: 0]; if (backend != NIL) backend->ProcessSystemMessages(event); } - (NSDragOperation) draggingEntered: (id) sender { NSPasteboard *pasteBoard = [sender draggingPasteboard]; NSDragOperation sourceDragMask = [sender draggingSourceOperationMask]; if ([[pasteBoard types] containsObject: NSFilenamesPboardType] && sourceDragMask & NSDragOperationGeneric) { return NSDragOperationGeneric; } return NSDragOperationNone; } - (BOOL) performDragOperation: (id) sender { [self processEvent: NSApplicationDropFiles withData: (NSInteger) sender]; return YES; } /* Internal use only. */ - (id) internalInitWithAttributes { [super initWithContentRect: contentRect styleMask: styleMask backing: NSBackingStoreBuffered defer: YES]; return self; } - (void) internalSetFrameWithAttributes { [self setFrame: frameRect display: YES]; } - (void) internalSetMinSizeWithAttributes { [self setContentMinSize: minSize]; } - (void) internalSetMaxSizeWithAttributes { [self setContentMaxSize: maxSize]; } @end #if defined MAC_OS_X_VERSION_10_6 && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 @interface CocoaWindowDelegate : NSObject { } #else @interface CocoaWindowDelegate : NSObject { } #endif - (void) handleNotification: (NSNotification *) note as: (int) type; - (BOOL) windowShouldClose: (NSWindow *) sender; - (void) windowDidMove: (NSNotification *) note; - (void) windowDidResize: (NSNotification *) note; - (void) windowWillEnterFullScreen: (NSNotification *) note; - (void) windowDidExitFullScreen: (NSNotification *) note; - (void) windowDidBecomeKey: (NSNotification *) note; - (void) windowDidResignKey: (NSNotification *) note; @end @implementation CocoaWindowDelegate - (BOOL) windowShouldClose: (NSWindow *) sender { WindowCocoa *backend = WindowCocoa::GetWindowBackend(sender); if (backend != NIL && !backend->doClose.Call()) return NO; return YES; } - (void) handleNotification: (NSNotification *) note as: (int) type { WindowCocoa *backend = WindowCocoa::GetWindowBackend([note object]); NSEvent *event = [NSEvent otherEventWithType: NSApplicationDefined location: NSMakePoint(0, 0) modifierFlags: 0 timestamp: 0 windowNumber: [[note object] windowNumber] context: nil subtype: type data1: 0 data2: 0]; if (backend != NIL) backend->ProcessSystemMessages(event); } - (void) windowDidMove: (NSNotification *) note { [self handleNotification: note as: NSApplicationMove]; } - (void) windowDidResize: (NSNotification *) note { [self handleNotification: note as: NSApplicationResize]; } - (void) windowWillEnterFullScreen: (NSNotification *) note { [(CocoaWindow *) [note object] setZooming: YES]; } - (void) windowDidExitFullScreen: (NSNotification *) note { [(CocoaWindow *) [note object] setZooming: NO]; } - (void) windowDidBecomeKey: (NSNotification *) note { [self handleNotification: note as: NSApplicationFocus]; } - (void) windowDidResignKey: (NSNotification *) note { [self handleNotification: note as: NSApplicationUnfocus]; } @end @interface CocoaCircularProgress : NSView { BOOL hidden; float progress; } - (id) init; - (void) setHidden: (BOOL) value; - (void) setProgress: (float) value; @end @implementation CocoaCircularProgress - (id) init { [super init]; hidden = NO; progress = 0.0; return self; } - (void) drawRect: (NSRect) dirtyRect { [[NSApp applicationIconImage] drawInRect: [self bounds] fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0]; if (hidden) return; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSRect badgeRect = [self bounds]; badgeRect.origin.x = NSWidth(badgeRect) - 0.4 * NSWidth(badgeRect) - 5.0; badgeRect.origin.y = badgeRect.origin.y + 5.0; badgeRect.size.width = 0.4 * NSWidth(badgeRect); badgeRect.size.height = (int) (0.4 * badgeRect.size.height); CGFloat badgeRadius = NSMidY(badgeRect); NSPoint badgeCenter = NSMakePoint(NSMidX(badgeRect), NSMidY(badgeRect)); /* Draw the background. */ [NSGraphicsContext saveGraphicsState]; NSColor *bgrdColor = [NSColor colorWithCalibratedRed: 0.85 green: 0.85 blue: 0.85 alpha: 1.0]; NSColor *bgrdHighlight = [bgrdColor blendedColorWithFraction: 0.85 ofColor: [NSColor whiteColor]]; NSGradient *bgrdGradient = [[[NSGradient alloc] initWithStartingColor: bgrdHighlight endingColor: bgrdColor] autorelease]; NSBezierPath *badgeEdge = [NSBezierPath bezierPathWithOvalInRect: badgeRect]; [badgeEdge addClip]; [bgrdGradient drawFromCenter: badgeCenter radius: 0.0 toCenter: badgeCenter radius: badgeRadius options: 0]; [NSGraphicsContext restoreGraphicsState]; /* Compute the slice. */ NSColor *sliceColor = [NSColor colorWithCalibratedRed: 0.3 green: 0.55 blue: 0.8 alpha: 1.0]; NSColor *sliceHighlight = [sliceColor blendedColorWithFraction: 0.4 ofColor: [NSColor whiteColor]]; NSGradient *sliceGradient = [[[NSGradient alloc] initWithStartingColor: sliceHighlight endingColor: sliceColor] autorelease]; NSBezierPath *progressSlice = [NSBezierPath bezierPathWithOvalInRect: badgeRect]; if (progress < 1.0) { CGFloat endAngle = 90.0 - 360.0 * progress; if (endAngle < 0.0) endAngle += 360.0; progressSlice = [NSBezierPath bezierPath]; [progressSlice moveToPoint: badgeCenter]; [progressSlice appendBezierPathWithArcWithCenter: badgeCenter radius: badgeRadius startAngle: 90.0 endAngle: endAngle clockwise: YES]; [progressSlice closePath]; } /* Draw the slice. */ [NSGraphicsContext saveGraphicsState]; [progressSlice addClip]; [sliceGradient drawFromCenter: badgeCenter radius: 0.0 toCenter: badgeCenter radius: badgeRadius options: 0]; [NSGraphicsContext restoreGraphicsState]; /* Draw the edge. */ [NSGraphicsContext saveGraphicsState]; [[NSColor whiteColor] set]; NSShadow *shadow = [[[NSShadow alloc] init] autorelease]; [shadow setShadowOffset: NSMakeSize(0, -2)]; [shadow setShadowBlurRadius: 2]; [shadow set]; [badgeEdge setLineWidth: 2]; [badgeEdge stroke]; [NSGraphicsContext restoreGraphicsState]; [pool release]; } - (void) setHidden: (BOOL) value { hidden = value; } - (void) setProgress: (float) value { progress = value; } @end S::Int S::GUI::WindowCocoa::Initialize() { /* Register for cursor events. */ Cursor::internalSetCursor.Connect(&WindowCocoa::SetCursor); Cursor::internalRemoveCursor.Connect(&WindowCocoa::RemoveCursor); return Success(); } S::Int S::GUI::WindowCocoa::Free() { /* Unregister cursor event handlers. */ Cursor::internalSetCursor.Disconnect(&WindowCocoa::SetCursor); Cursor::internalRemoveCursor.Disconnect(&WindowCocoa::RemoveCursor); return Success(); } S::GUI::WindowCocoa::WindowCocoa(Void *iWindow) { type = WINDOW_COCOA; wnd = nil; progressView = nil; wid = windowBackends.Add(this); minSize = Size(160, 24); maxSize = Size(32768, 32768); zoomed = False; fontSize = Surface().GetSurfaceDPI() / 96.0; flags = 0; pasteBoard = nil; enableDropFiles = False; } S::GUI::WindowCocoa::~WindowCocoa() { if (wnd != nil) [wnd release]; if (progressView != nil) [progressView release]; windowBackends.Remove(wid); } S::Void *S::GUI::WindowCocoa::GetSystemWindow() const { return (Void *) wnd; } S::GUI::WindowCocoa *S::GUI::WindowCocoa::GetWindowBackend(NSWindow *wnd) { if (wnd == nil) return NIL; for (Int i = 0; i < windowBackends.Length(); i++) { WindowCocoa *window = windowBackends.GetNth(i); if (window != NIL) { if (window->wnd == wnd) return window; } } return NIL; } S::Input::Keyboard::Key S::GUI::WindowCocoa::ConvertKey(Int keySym) { Input::Keyboard::Key key = Input::Keyboard::KeyOther; switch (keySym) { case NSLeftArrowFunctionKey: key = Input::Keyboard::KeyLeft; break; case NSUpArrowFunctionKey: key = Input::Keyboard::KeyUp; break; case NSRightArrowFunctionKey: key = Input::Keyboard::KeyRight; break; case NSDownArrowFunctionKey: key = Input::Keyboard::KeyDown; break; case NSHomeFunctionKey: key = Input::Keyboard::KeyHome; break; case NSEndFunctionKey: key = Input::Keyboard::KeyEnd; break; case NSInsertFunctionKey: key = Input::Keyboard::KeyInsert; break; case NSDeleteFunctionKey: key = Input::Keyboard::KeyDelete; break; case NSPrevFunctionKey: key = Input::Keyboard::KeyPrior; break; case NSNextFunctionKey: key = Input::Keyboard::KeyNext; break; case NSEnterCharacter: case NSCarriageReturnCharacter: key = Input::Keyboard::KeyReturn; break; case NSDeleteCharacter: key = Input::Keyboard::KeyBack; break; case NSTabCharacter: case NSBackTabCharacter: key = Input::Keyboard::KeyTab; break; case 0x20: key = Input::Keyboard::KeySpace; break; case 0x1B: key = Input::Keyboard::KeyEscape; break; case NSF1FunctionKey: key = Input::Keyboard::KeyF1; break; case NSF2FunctionKey: key = Input::Keyboard::KeyF2; break; case NSF3FunctionKey: key = Input::Keyboard::KeyF3; break; case NSF4FunctionKey: key = Input::Keyboard::KeyF4; break; case NSF5FunctionKey: key = Input::Keyboard::KeyF5; break; case NSF6FunctionKey: key = Input::Keyboard::KeyF6; break; case NSF7FunctionKey: key = Input::Keyboard::KeyF7; break; case NSF8FunctionKey: key = Input::Keyboard::KeyF8; break; case NSF9FunctionKey: key = Input::Keyboard::KeyF9; break; case NSF10FunctionKey: key = Input::Keyboard::KeyF10; break; case NSF11FunctionKey: key = Input::Keyboard::KeyF11; break; case NSF12FunctionKey: key = Input::Keyboard::KeyF12; break; case NSF13FunctionKey: key = Input::Keyboard::KeyF13; break; case NSF14FunctionKey: key = Input::Keyboard::KeyF14; break; case NSF15FunctionKey: key = Input::Keyboard::KeyF15; break; case NSF16FunctionKey: key = Input::Keyboard::KeyF16; break; case NSF17FunctionKey: key = Input::Keyboard::KeyF17; break; case NSF18FunctionKey: key = Input::Keyboard::KeyF18; break; case NSF19FunctionKey: key = Input::Keyboard::KeyF19; break; case NSF20FunctionKey: key = Input::Keyboard::KeyF20; break; case NSF21FunctionKey: key = Input::Keyboard::KeyF21; break; case NSF22FunctionKey: key = Input::Keyboard::KeyF22; break; case NSF23FunctionKey: key = Input::Keyboard::KeyF23; break; case NSF24FunctionKey: key = Input::Keyboard::KeyF24; break; } if (keySym >= '0' && keySym <= '9') key = (Input::Keyboard::Key) keySym; else if (keySym >= 'A' && keySym <= 'Z') key = (Input::Keyboard::Key) keySym; else if (keySym >= 'a' && keySym <= 'z') key = (Input::Keyboard::Key) (keySym + ('A' - 'a')); return key; } S::Int S::GUI::WindowCocoa::ProcessSystemMessages(NSEvent *e) { static Int focusWndID = -1; /* Lock application while processing messages. */ Application::Lock lock; /* Convert Cocoa events to smooth messages. */ NSArray *screens = [NSScreen screens]; NSRect firstScreen = [[screens objectAtIndex: 0] frame]; switch ([e type]) { /* Mouse events: */ case NSMouseMoved: case NSMouseEntered: case NSMouseExited: case NSLeftMouseDown: case NSLeftMouseDragged: case NSLeftMouseUp: case NSRightMouseDown: case NSRightMouseDragged: case NSRightMouseUp: /* Update pointer position in Input::Pointer. */ if ([e type] == NSMouseExited) Input::Pointer::UpdatePosition(NIL, [NSEvent mouseLocation].x, firstScreen.size.height - [NSEvent mouseLocation].y); else Input::Pointer::UpdatePosition(Window::GetWindow((Void *) [e window]), [NSEvent mouseLocation].x, firstScreen.size.height - [NSEvent mouseLocation].y); /* Reject if a modal window is active. */ if (([e type] == NSLeftMouseDown || [e type] == NSRightMouseDown) && !(flags & WF_TOPMOST) && ( [NSApp modalWindow] != nil && [NSApp modalWindow] != wnd && [[NSApp modalWindow] isVisible])) break; /* Grab the keyboard focus if we don't have it already. */ if (focusWndID != wid && ([e type] == NSLeftMouseDown || [e type] == NSRightMouseDown)) { WindowCocoa *focusWnd = windowBackends.Get(focusWndID); if (focusWnd != NIL) focusWnd->onEvent.Call(SM_LOSEFOCUS, Window::GetWindow((Void *) wnd)->GetHandle(), 0); focusWndID = wid; onEvent.Call(SM_GETFOCUS, 0, 0); } /* Pass message to smooth window. */ if ([e type] == NSLeftMouseDown) onEvent.Call(SM_LBUTTONDOWN, 0, 0); else if ([e type] == NSLeftMouseUp) onEvent.Call(SM_LBUTTONUP, 0, 0); else if ([e type] == NSRightMouseDown) onEvent.Call(SM_RBUTTONDOWN, 0, 0); else if ([e type] == NSRightMouseUp) onEvent.Call(SM_RBUTTONUP, 0, 0); else onEvent.Call(SM_MOUSEMOVE, 0, 0); if ([e type] == NSLeftMouseDown && [e clickCount] == 2) onEvent.Call(SM_LBUTTONDBLCLK, 0, 0); else if ([e type] == NSRightMouseDown && [e clickCount] == 2) onEvent.Call(SM_RBUTTONDBLCLK, 0, 0); break; case NSOtherMouseDown: case NSOtherMouseDragged: case NSOtherMouseUp: /* Update pointer position in Input::Pointer. */ Input::Pointer::UpdatePosition(Window::GetWindow((Void *) [e window]), [NSEvent mouseLocation].x, firstScreen.size.height - [NSEvent mouseLocation].y); /* Reject if a modal window is active. */ if ([e type] == NSOtherMouseDown && !(flags & WF_TOPMOST) && ( [NSApp modalWindow] != nil && [NSApp modalWindow] != wnd && [[NSApp modalWindow] isVisible])) break; /* Grab the keyboard focus if we don't have it already. */ if (focusWndID != wid && [e type] == NSOtherMouseDown) { WindowCocoa *focusWnd = windowBackends.Get(focusWndID); if (focusWnd != NIL) focusWnd->onEvent.Call(SM_LOSEFOCUS, Window::GetWindow((Void *) wnd)->GetHandle(), 0); focusWndID = wid; onEvent.Call(SM_GETFOCUS, 0, 0); } /* Pass message to smooth window. */ if ([e type] == NSOtherMouseDown) { if ([e buttonNumber] == 2) onEvent.Call(SM_MBUTTONDOWN, 0, 0); } else if ([e type] == NSOtherMouseUp) { if ([e buttonNumber] == 2) onEvent.Call(SM_MBUTTONUP, 0, 0); } else onEvent.Call(SM_MOUSEMOVE, 0, 0); if ([e type] == NSOtherMouseDown && [e clickCount] == 2) { if ([e buttonNumber] == 2) onEvent.Call(SM_MBUTTONDBLCLK, 0, 0); } break; case NSScrollWheel: /* Pass message to smooth window. */ if ([e respondsToSelector: @selector(hasPreciseScrollingDeltas)] && ((BOOL (*)(id, SEL)) [e methodForSelector: @selector(hasPreciseScrollingDeltas)])(e, @selector(hasPreciseScrollingDeltas))) onEvent.Call(SM_MOUSEWHEEL, ((CGFloat (*)(id, SEL)) [e methodForSelector: @selector(scrollingDeltaY)])(e, @selector(scrollingDeltaY)), 0); else onEvent.Call(SM_MOUSEWHEEL, [e deltaY] * 50, 0); break; /* Keyboard events: */ case NSKeyDown: if ([[e charactersIgnoringModifiers] length] >= 1) { NSString *characters = [e charactersIgnoringModifiers]; Input::Keyboard::UpdateKeyState(ConvertKey([characters characterAtIndex: 0]), True); onEvent.Call(SM_KEYDOWN, ConvertKey([characters characterAtIndex: 0]), 0); } break; case NSKeyUp: if ([[e charactersIgnoringModifiers] length] >= 1) { NSString *characters = [e charactersIgnoringModifiers]; Input::Keyboard::UpdateKeyState(ConvertKey([characters characterAtIndex: 0]), False); onEvent.Call(SM_KEYUP, ConvertKey([characters characterAtIndex: 0]), 0); } break; case NSFlagsChanged: Input::Keyboard::UpdateKeyState(Input::Keyboard::KeyShift, [e modifierFlags] & NSShiftKeyMask); Input::Keyboard::UpdateKeyState(Input::Keyboard::KeyControl, [e modifierFlags] & NSControlKeyMask); Input::Keyboard::UpdateKeyState(Input::Keyboard::KeyCommand, [e modifierFlags] & NSCommandKeyMask); Input::Keyboard::UpdateKeyState(Input::Keyboard::KeyAlt, [e modifierFlags] & NSAlternateKeyMask); if ([e modifierFlags] & NSShiftKeyMask) onEvent.Call(SM_KEYDOWN, Input::Keyboard::KeyShift, 0); if ([e modifierFlags] & NSControlKeyMask) onEvent.Call(SM_KEYDOWN, Input::Keyboard::KeyControl, 0); if ([e modifierFlags] & NSCommandKeyMask) onEvent.Call(SM_KEYDOWN, Input::Keyboard::KeyCommand, 0); if ([e modifierFlags] & NSAlternateKeyMask) onEvent.Call(SM_KEYDOWN, Input::Keyboard::KeyAlt, 0); break; /* Custom events: */ case NSApplicationDefined: /* Paint events: */ if ([e subtype] == NSApplicationPaint) { /* Get drawing area. */ NSRect *rect = (NSRect *) [e data1]; /* Fill update rect. */ if (updateRect == Rect()) { updateRect.left = rect->origin.x; updateRect.top = rect->origin.y; updateRect.right = rect->origin.x + rect->size.width; updateRect.bottom = rect->origin.y + rect->size.height; } else { updateRect.left = Math::Min(updateRect.left, Int(rect->origin.x)); updateRect.top = Math::Min(updateRect.top, Int(rect->origin.y)); updateRect.right = Math::Max(updateRect.right, Int(rect->origin.x + rect->size.width)); updateRect.bottom = Math::Max(updateRect.bottom, Int(rect->origin.y + rect->size.height)); } onEvent.Call(SM_PAINT, 0, 0); updateRect = Rect(); } /* Window state change events: */ if ([e subtype] == NSApplicationMap) { /* Set internal focus window. */ focusWndID = wid; onEvent.Call(SM_GETFOCUS, 0, 0); } if ([e subtype] == NSApplicationUnmap) { /* Clear internal focus window. */ if (focusWndID == wid) focusWndID = -1; } if ([e subtype] == NSApplicationMove || [e subtype] == NSApplicationResize) { /* Update window metrics. */ UpdateMetrics([e subtype] == NSApplicationResize); /* Update zoom state and restored rect. */ NSRect contentRect = [wnd contentRectForFrameRect: [wnd frame]]; contentRect.origin.y = firstScreen.size.height - (contentRect.origin.y + contentRect.size.height); Point pos = Point(contentRect.origin.x, contentRect.origin.y); Size size = (Size(contentRect.size.width, contentRect.size.height) - sizeModifier) / fontSize; if (![wnd isZoomed] && ![(CocoaWindow *) wnd isZooming]) restoredRect = Rect(pos, size); if ( [wnd isZoomed] && !zoomed) onMaximize.Emit(); else if (![wnd isZoomed] && zoomed) onRestore.Emit(); zoomed = [wnd isZoomed]; if (zoomed) [(CocoaWindow *) wnd setZooming: NO]; } /* Focus events: */ if ([e subtype] == NSApplicationFocus) { focusWndID = wid; onEvent.Call(SM_GETFOCUS, 0, 0); } if ([e subtype] == NSApplicationUnfocus) { Input::Keyboard::ResetKeyState(); /* Get the window that now has the focus. */ { NSWindow *cocoaFocusWnd = [NSApp keyWindow]; Window *focusWnd = Window::GetWindow((Void *) cocoaFocusWnd); onEvent.Call(SM_LOSEFOCUS, focusWnd != NIL ? focusWnd->GetHandle() : -1, 0); } } /* Keyboard events: */ if ([e subtype] == NSApplicationInsertText) { /* Call SM_CHAR event for each character in input string. */ NSString *characters = (NSString *) [e data1]; String string; string.ImportFrom("UTF-8", [characters UTF8String]); for (Int i = 0; i < string.Length(); i++) onEvent.Call(SM_CHAR, string[i], 0); } /* Drag & drop events: */ if ([e subtype] == NSApplicationDropFiles) { Window *window = Window::GetWindow((Void *) wnd); Input::Pointer::UpdatePosition(window, [NSEvent mouseLocation].x, firstScreen.size.height - [NSEvent mouseLocation].y); id info = (id) [e data1]; Point position = window->GetMousePosition(); pasteBoard = [info draggingPasteboard]; onEvent.Call(SM_DROPFILES, position.x, position.y); } break; } /* Return from the active loop after processing an event. */ NSWindow *modalWindow = [NSApp modalWindow]; NSWindow *keyWindow = [NSApp keyWindow]; WindowCocoa *keyWindowBackend = GetWindowBackend(keyWindow); if ((modalWindow == wnd && (keyWindow != nil && keyWindow != wnd && keyWindowBackend != NIL && !(keyWindowBackend->flags & WF_TOPMOST))) || (keyWindow == wnd && (modalWindow == nil || ![modalWindow isVisible]))) [NSApp stop: nil]; return Success(); } S::Int S::GUI::WindowCocoa::Open(const String &title, const Point &pos, const Size &size, Int iFlags) { flags = iFlags; restoredRect = Rect(pos, size); NSArray *screens = [NSScreen screens]; NSRect firstScreen = [[screens objectAtIndex: 0] frame]; NSRect contentRect = NSMakeRect(pos.x, firstScreen.size.height - (pos.y + Math::Round(size.cy * fontSize) + sizeModifier.cy), Math::Round(size.cx * fontSize) + sizeModifier.cx, Math::Round(size.cy * fontSize) + sizeModifier.cy); NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; if (flags & WF_NORESIZE ) styleMask ^= NSResizableWindowMask; if (flags & WF_THINBORDER) styleMask = NSBorderlessWindowMask; wnd = [[CocoaWindow alloc] initWithContentRect: contentRect styleMask: styleMask]; if (wnd != nil) { /* We will explicitly release the window later. */ [wnd setReleasedWhenClosed: NO]; /* Do not show the resize grip on older macOS versions. */ [wnd setShowsResizeIndicator: NO]; /* Init content view and delegate. */ NSView *contentView = [[[CocoaView alloc] initWithFrame: contentRect] autorelease]; if ([NSThread isMainThread]) [wnd setContentView: contentView]; else [wnd performSelectorOnMainThread: @selector(setContentView:) withObject: contentView waitUntilDone: YES]; [wnd setDelegate: [[[CocoaWindowDelegate alloc] init] autorelease]]; /* Create drawing surface. */ if ((flags & WF_THINBORDER) || (flags & WF_NORESIZE)) drawSurface = new Surface((Void *) wnd, size * fontSize + sizeModifier); else drawSurface = new Surface((Void *) wnd); drawSurface->SetSize(size * fontSize + sizeModifier); [wnd useOptimizedDrawing: YES]; /* Set window title. */ SetTitle(title); /* Update metrics for actually allocated window. */ UpdateMetrics(False); /* Set window level for topmost windows. */ if (flags & WF_TOPMOST) [wnd setLevel: NSPopUpMenuWindowLevel]; /* Enable dropping files if requested. */ if (enableDropFiles) EnableDropFiles(True); /* Emit onCreate signal. */ onCreate.Emit(); return Success(); } return Error(); } S::Int S::GUI::WindowCocoa::Close() { if (wnd == nil) return Success(); /* Delete surface. */ if (drawSurface != NIL) delete drawSurface; drawSurface = NIL; /* Hide window. */ [wnd orderOut: nil]; /* Emit onDestroy signal. */ onDestroy.Emit(); /* Stop active loop after the window is closed. */ if (flags & WF_MODAL) [NSApp abortModal]; else if (Window::nOfActiveWindows == 0) [NSApp stop: nil]; return Success(); } S::Int S::GUI::WindowCocoa::RequestClose() { if (wnd == nil) return Success(); if ([wnd hasCloseBox]) { if ([NSThread isMainThread]) [wnd performClose: nil]; else [wnd performSelectorOnMainThread: @selector(performClose:) withObject: nil waitUntilDone: YES]; } else { if ([NSThread isMainThread]) [wnd close]; else [wnd performSelectorOnMainThread: @selector(close) withObject: nil waitUntilDone: YES]; } return Success(); } S::Int S::GUI::WindowCocoa::SetTitle(const String &nTitle) { if (wnd == nil) return Error(); NSString *title = [NSString stringWithUTF8String: nTitle.ConvertTo("UTF-8")]; if ([NSThread isMainThread]) [wnd setTitle: title]; else [wnd performSelectorOnMainThread: @selector(setTitle:) withObject: title waitUntilDone: YES]; return Success(); } S::Int S::GUI::WindowCocoa::EnableDropFiles(Bool nEnableDropFiles) { enableDropFiles = nEnableDropFiles; if (wnd != nil) { if (enableDropFiles) [wnd registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; else [wnd unregisterDraggedTypes]; } return Success(); } const S::Array &S::GUI::WindowCocoa::GetDroppedFiles() const { if (pasteBoard == nil) return WindowBackend::GetDroppedFiles(); static Array fileNames; fileNames.RemoveAll(); /* Query dropped files. */ NSArray *files = [pasteBoard propertyListForType: NSFilenamesPboardType]; for (NSString *file in files) { String fileName; fileName.ImportFrom("UTF-8", [file UTF8String]); fileNames.Add(fileName); } return fileNames; } S::Int S::GUI::WindowCocoa::SetMinimumSize(const Size &nMinSize) { minSize = nMinSize; if (wnd == nil) return Success(); [(CocoaWindow *) wnd setMinSize: NSMakeSize(Math::Round(minSize.cx * fontSize) + sizeModifier.cx, Math::Round(minSize.cy * fontSize) + sizeModifier.cy)]; NSRect contentRect = [wnd contentRectForFrameRect: [wnd frame]]; if (contentRect.size.width < Math::Round(minSize.cx * fontSize) + sizeModifier.cx || contentRect.size.height < Math::Round(minSize.cy * fontSize) + sizeModifier.cy) { [(CocoaWindow *) wnd setFrame: [wnd frameRectForContentRect: NSMakeRect(contentRect.origin.x, contentRect.origin.y + contentRect.size.height - Math::Max((Int) contentRect.size.height, (Int) Math::Round(minSize.cy * fontSize) + sizeModifier.cy), Math::Max((Int) contentRect.size.width, (Int) Math::Round(minSize.cx * fontSize) + sizeModifier.cx), Math::Max((Int) contentRect.size.height, (Int) Math::Round(minSize.cy * fontSize) + sizeModifier.cy))]]; } return Success(); } S::Int S::GUI::WindowCocoa::SetMaximumSize(const Size &nMaxSize) { maxSize = nMaxSize; if (wnd == nil) return Success(); [(CocoaWindow *) wnd setMaxSize: NSMakeSize(Math::Round(maxSize.cx * fontSize) + sizeModifier.cx, Math::Round(maxSize.cy * fontSize) + sizeModifier.cy)]; NSRect contentRect = [wnd contentRectForFrameRect: [wnd frame]]; if (contentRect.size.width > Math::Round(maxSize.cx * fontSize) + sizeModifier.cx || contentRect.size.height > Math::Round(maxSize.cy * fontSize) + sizeModifier.cy) { [(CocoaWindow *) wnd setFrame: [wnd frameRectForContentRect: NSMakeRect(contentRect.origin.x, contentRect.origin.y + contentRect.size.height - Math::Max((Int) contentRect.size.height, (Int) Math::Round(minSize.cy * fontSize) + sizeModifier.cy), Math::Max((Int) contentRect.size.width, (Int) Math::Round(minSize.cx * fontSize) + sizeModifier.cx), Math::Max((Int) contentRect.size.height, (Int) Math::Round(minSize.cy * fontSize) + sizeModifier.cy))]]; } return Success(); } S::Int S::GUI::WindowCocoa::Show() { if (wnd == nil) return Success(); /* Show window. */ if ([NSThread isMainThread]) [wnd makeKeyAndOrderFront: nil]; else [wnd performSelectorOnMainThread: @selector(makeKeyAndOrderFront:) withObject: nil waitUntilDone: YES]; /* Set minimum and maximum size. */ if (!(flags & WF_THINBORDER)) { SetMinimumSize(minSize); SetMaximumSize(maxSize); } /* Update window metrics. */ UpdateMetrics(False); /* Set update rect and send paint event for new window. */ NSRect contentRect = [wnd contentRectForFrameRect: [wnd frame]]; updateRect = Rect(Point(0, 0), Size(contentRect.size.width, contentRect.size.height)); onEvent.Call(SM_PAINT, 0, 0); updateRect = Rect(); return Success(); } S::Int S::GUI::WindowCocoa::Hide() { if (wnd == nil) return Success(); if ([NSThread isMainThread]) [wnd orderOut: nil]; else [wnd performSelectorOnMainThread: @selector(orderOut:) withObject: nil waitUntilDone: YES]; return Success(); } S::Int S::GUI::WindowCocoa::SetMetrics(const Point &nPos, const Size &nSize) { if (wnd == nil) return Success(); NSArray *screens = [NSScreen screens]; NSRect firstScreen = [[screens objectAtIndex: 0] frame]; [(CocoaWindow *) wnd setFrame: [wnd frameRectForContentRect: NSMakeRect(nPos.x, firstScreen.size.height - (nPos.y + Math::Round(nSize.cy * fontSize) + sizeModifier.cy), Math::Round(nSize.cx * fontSize) + sizeModifier.cx, Math::Round(nSize.cy * fontSize) + sizeModifier.cy)]]; return Success(); } S::Int S::GUI::WindowCocoa::Maximize() { if (wnd == nil) return Success(); if (!zoomed) { if ([NSThread isMainThread]) [wnd zoom: nil]; else [wnd performSelectorOnMainThread: @selector(zoom:) withObject: nil waitUntilDone: YES]; } return Success(); } S::Int S::GUI::WindowCocoa::Raise() { if (wnd == nil) return Success(); if ([NSThread isMainThread]) [wnd makeKeyAndOrderFront: nil]; else [wnd performSelectorOnMainThread: @selector(makeKeyAndOrderFront:) withObject: nil waitUntilDone: YES]; return Success(); } S::Void S::GUI::WindowCocoa::UpdateMetrics(Bool resized) { /* Update metrics and emit window metrics event. */ NSArray *screens = [NSScreen screens]; NSRect firstScreen = [[screens objectAtIndex: 0] frame]; NSRect contentRect = [wnd contentRectForFrameRect: [wnd frame]]; contentRect.origin.y = firstScreen.size.height - (contentRect.origin.y + contentRect.size.height); Point pos = Point(contentRect.origin.x, contentRect.origin.y); Size size = Size(contentRect.size.width, contentRect.size.height) / fontSize; if (resized && drawSurface != NIL) drawSurface->SetSize(Size(contentRect.size.width, contentRect.size.height)); onEvent.Call(SM_WINDOWMETRICS, ((pos.x + 32768) << 16) | (pos.y + 32768), ((size.cx + 32768) << 16) | (size.cy + 32768)); } S::Int S::GUI::WindowCocoa::SetProgressIndicator(Window::ProgressIndicatorState state, Float value) { if (progressView == nil) { progressView = [[CocoaCircularProgress alloc] init]; [[NSApp dockTile] setContentView: progressView]; } CocoaCircularProgress *circularProgress = (CocoaCircularProgress *) progressView; switch (state) { case Window::ProgressIndicatorNone: [circularProgress setHidden: YES]; break; case Window::ProgressIndicatorNormal: case Window::ProgressIndicatorPaused: if (value >= 0) [circularProgress setProgress: value / 100]; [circularProgress setHidden: NO]; break; } if ([NSThread isMainThread]) [[NSApp dockTile] display]; else [[NSApp dockTile] performSelectorOnMainThread: @selector(display) withObject: nil waitUntilDone: NO]; return Success(); } S::Void S::GUI::WindowCocoa::SetCursor(Cursor *cursor, const Point &point) { CocoaWindow *window = (CocoaWindow *) cursor->GetContainerWindow()->GetSystemWindow(); if (window != NIL) { CocoaView *view = (CocoaView *) [window contentView]; [view setCursor: cursor position: point]; } } S::Void S::GUI::WindowCocoa::RemoveCursor(Cursor *cursor) { CocoaWindow *window = (CocoaWindow *) cursor->GetContainerWindow()->GetSystemWindow(); CocoaView *view = (CocoaView *) [window contentView]; [view removeCursor: cursor]; } smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/gdi/000077500000000000000000000000001516402577000240255ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/gdi/Makefile000066400000000000000000000006711516402577000254710ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_WIN32),True) OBJECTS += droptarget.o windowgdi.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/gdi/droptarget.cpp000066400000000000000000000121661516402577000267120ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const CLIPFORMAT smooth::GUI::DropTarget::CF_SHELLIDLIST = RegisterClipboardFormat(CFSTR_SHELLIDLIST); smooth::GUI::DropTarget::DropTarget(WindowGDI *backend) { refCount = 1; data = NIL; this->backend = backend; } smooth::GUI::DropTarget::~DropTarget() { } smooth::Array smooth::GUI::DropTarget::GetFilesFromHDROP(HDROP hDrop) { Array fileNames; /* Query number of files dropped. */ Int nOfFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); /* Query dropped files. */ Buffer buffer(32768); for (Int i = 0; i < nOfFiles; i++) { DragQueryFile(hDrop, i, buffer, buffer.Size()); fileNames.Add(Backends::BackendWin32::GetFullPathName(String(buffer))); } return fileNames; } smooth::Array smooth::GUI::DropTarget::GetFilesFromCIDA(CIDA *cida) { Array fileNames; /* Get parent folder descriptor. */ LPCITEMIDLIST parentFolder = LPCITEMIDLIST(((LPBYTE) cida) + cida->aoffset[0]); for (UnsignedInt i = 0; i < cida->cidl; ++i) { /* Get shell item. */ IShellItem *shellItem = NIL; if (SHCreateShellItem(parentFolder, NULL, LPCITEMIDLIST(((LPBYTE) cida) + cida->aoffset[i + 1]), &shellItem) != S_OK) continue; /* Query path from shell item. */ wchar_t *path = NIL; if (shellItem->GetDisplayName(SIGDN_FILESYSPATH, &path) == S_OK) { fileNames.Add(Backends::BackendWin32::GetFullPathName(path)); CoTaskMemFree(path); } shellItem->Release(); } return fileNames; } smooth::Array smooth::GUI::DropTarget::GetDroppedFiles() { if (data == NIL) return Array(); Array fileNames; /* Try HDROP and ShellIDList clipboard formats. */ FORMATETC formatHDrop = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; FORMATETC formatIDList = { CF_SHELLIDLIST, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM storageMedium = { 0 }; if (data->GetData(&formatIDList, &storageMedium) == S_OK) { /* Get files from ShellIDList objects. */ if (CIDA *cida = (CIDA *) GlobalLock(storageMedium.hGlobal)) { fileNames = GetFilesFromCIDA(cida); GlobalUnlock(cida); } ReleaseStgMedium(&storageMedium); } else if (data->GetData(&formatHDrop, &storageMedium) == S_OK) { /* Get files from HDROP handle. */ if (HDROP hDrop = (HDROP) GlobalLock(storageMedium.hGlobal)) { fileNames = GetFilesFromHDROP(hDrop); GlobalUnlock(hDrop); } ReleaseStgMedium(&storageMedium); } return fileNames; } ULONG STDMETHODCALLTYPE smooth::GUI::DropTarget::AddRef() { return ++refCount; } ULONG STDMETHODCALLTYPE smooth::GUI::DropTarget::Release() { if (--refCount == 0) { delete this; return 0; } return refCount; } STDMETHODIMP smooth::GUI::DropTarget::QueryInterface(REFIID riid, void **ppvObject) { if (riid == IID_IUnknown) *ppvObject = (IUnknown *) this; else if (riid == IID_IDropTarget) *ppvObject = (IDropTarget *) this; else return E_NOINTERFACE; AddRef(); return S_OK; } STDMETHODIMP smooth::GUI::DropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { /* Look for supported drop formats. */ Bool formatSupported = False; if (*pdwEffect & DROPEFFECT_COPY) { IEnumFORMATETC *enumFormat = NIL; if (pDataObj->EnumFormatEtc(DATADIR_GET, &enumFormat) == S_OK) { FORMATETC format; while (enumFormat->Next(1, &format, NULL) == S_OK) { if (format.cfFormat != CF_HDROP && format.cfFormat != CF_SHELLIDLIST) continue; formatSupported = True; break; } enumFormat->Release(); } } /* Check if we found a supported format. */ if (formatSupported) { *pdwEffect = DROPEFFECT_COPY; data = pDataObj; data->AddRef(); } else { *pdwEffect = DROPEFFECT_NONE; } return S_OK; } STDMETHODIMP smooth::GUI::DropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { if (*pdwEffect & DROPEFFECT_COPY) *pdwEffect = DROPEFFECT_COPY; else *pdwEffect = DROPEFFECT_NONE; return S_OK; } STDMETHODIMP smooth::GUI::DropTarget::DragLeave() { /* Free data if any. */ if (data == NIL) return S_OK; data->Release(); data = NIL; return S_OK; } STDMETHODIMP smooth::GUI::DropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { /* Fire drop event. */ RECT windowRect; GetWindowRect((HWND) backend->GetSystemWindow(), &windowRect); backend->onEvent.Call(SM_DROPFILES, pt.x - windowRect.left, pt.y - windowRect.top); *pdwEffect = DROPEFFECT_COPY; /* Free data if any. */ if (data == NIL) return S_OK; data->Release(); data = NIL; return S_OK; } smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/gdi/windowgdi.cpp000077500000000000000000000762571516402577000265500ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2023 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #if !defined SM_CXPADDEDBORDER # define SM_CXPADDEDBORDER 92 #endif static HMODULE dwmapidll = NIL; typedef HRESULT (WINAPI *DWMSETWINDOWATTRIBUTE)(HWND, DWORD, LPCVOID, DWORD); static DWMSETWINDOWATTRIBUTE ex_DwmSetWindowAttribute = NIL; S::GUI::WindowBackend *CreateWindowGDI() { return new S::GUI::WindowGDI(); } S::Int windowGDITmp = S::GUI::WindowBackend::SetBackend(&CreateWindowGDI); S::Int addWindowGDIInitTmp = S::AddInitFunction(&S::GUI::WindowGDI::Initialize); S::Int addWindowGDIFreeTmp = S::AddFreeFunction(&S::GUI::WindowGDI::Free); S::Array S::GUI::WindowGDI::windowBackends; S::GUI::Cursor *S::GUI::WindowGDI::activeCursor = NIL; LRESULT CALLBACK S::GUI::WindowGDI::WindowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) { WindowGDI *smoothWindow = WindowGDI::GetWindowBackend(window); if (smoothWindow != NIL) { Int result = smoothWindow->ProcessSystemMessages(message, wParam, lParam); if (result == MessageProcessed) return 0; else if (result != MessageUnknown) return result; } return DefWindowProc(window, message, wParam, lParam); } S::Int S::GUI::WindowGDI::Initialize() { /* Load DWM API library. */ dwmapidll = LoadLibrary(L"dwmapi.dll"); ex_DwmSetWindowAttribute = (DWMSETWINDOWATTRIBUTE) GetProcAddress(dwmapidll, "DwmSetWindowAttribute"); /* Register for cursor events. */ Cursor::internalSetCursor.Connect(&WindowGDI::SetCursor); Cursor::internalRemoveCursor.Connect(&WindowGDI::RemoveCursor); return Success(); } S::Int S::GUI::WindowGDI::Free() { /* Unregister cursor event handlers. */ Cursor::internalSetCursor.Disconnect(&WindowGDI::SetCursor); Cursor::internalRemoveCursor.Disconnect(&WindowGDI::RemoveCursor); /* Free DWM API library. */ FreeLibrary(dwmapidll); return Success(); } S::GUI::WindowGDI::WindowGDI(Void *iWindow) { type = WINDOW_GDI; hwnd = NIL; wndclass = NIL; taskbar = NIL; className = String::FromInt(System::System::RequestGUID()); id = windowBackends.Add(this); minSize = Size(160, 24); minimized = False; maximized = False; frameSize = Size(GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER), GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)); fontSize = Surface().GetSurfaceDPI() / 96.0; flags = 0; sysIcon = (HICON) LoadImage(NIL, MAKEINTRESOURCE(32512), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADMAP3DCOLORS | LR_SHARED); destroyIcon = False; hDrop = NIL; dropTarget = NIL; enableDropFiles = False; restoredWndStyle = 0; } S::GUI::WindowGDI::~WindowGDI() { if (destroyIcon) DestroyIcon(sysIcon); if (taskbar != NIL) taskbar->Release(); windowBackends.Remove(id); } S::Void *S::GUI::WindowGDI::GetSystemWindow() const { return (Void *) hwnd; } S::GUI::WindowGDI *S::GUI::WindowGDI::GetWindowBackend(HWND hwnd) { if (hwnd == NIL) return NIL; foreach (WindowGDI *window, windowBackends) { if (window != NIL && window->hwnd == hwnd) return window; } return NIL; } S::Input::Keyboard::Key S::GUI::WindowGDI::ConvertKey(Int keySym) { Input::Keyboard::Key key = Input::Keyboard::KeyOther; switch (keySym) { case VK_LEFT: key = Input::Keyboard::KeyLeft; break; case VK_UP: key = Input::Keyboard::KeyUp; break; case VK_RIGHT: key = Input::Keyboard::KeyRight; break; case VK_DOWN: key = Input::Keyboard::KeyDown; break; case VK_HOME: key = Input::Keyboard::KeyHome; break; case VK_END: key = Input::Keyboard::KeyEnd; break; case VK_INSERT: key = Input::Keyboard::KeyInsert; break; case VK_DELETE: key = Input::Keyboard::KeyDelete; break; case VK_PRIOR: key = Input::Keyboard::KeyPrior; break; case VK_NEXT: key = Input::Keyboard::KeyNext; break; case VK_RETURN: key = Input::Keyboard::KeyReturn; break; case VK_BACK: key = Input::Keyboard::KeyBack; break; case VK_TAB: key = Input::Keyboard::KeyTab; break; case VK_SPACE: key = Input::Keyboard::KeySpace; break; case VK_SHIFT: key = Input::Keyboard::KeyShift; break; case VK_CONTROL: key = Input::Keyboard::KeyControl; break; case VK_MENU: key = Input::Keyboard::KeyAlt; break; case VK_ESCAPE: key = Input::Keyboard::KeyEscape; break; case VK_F1: key = Input::Keyboard::KeyF1; break; case VK_F2: key = Input::Keyboard::KeyF2; break; case VK_F3: key = Input::Keyboard::KeyF3; break; case VK_F4: key = Input::Keyboard::KeyF4; break; case VK_F5: key = Input::Keyboard::KeyF5; break; case VK_F6: key = Input::Keyboard::KeyF6; break; case VK_F7: key = Input::Keyboard::KeyF7; break; case VK_F8: key = Input::Keyboard::KeyF8; break; case VK_F9: key = Input::Keyboard::KeyF9; break; case VK_F10: key = Input::Keyboard::KeyF10; break; case VK_F11: key = Input::Keyboard::KeyF11; break; case VK_F12: key = Input::Keyboard::KeyF12; break; case VK_F13: key = Input::Keyboard::KeyF13; break; case VK_F14: key = Input::Keyboard::KeyF14; break; case VK_F15: key = Input::Keyboard::KeyF15; break; case VK_F16: key = Input::Keyboard::KeyF16; break; case VK_F17: key = Input::Keyboard::KeyF17; break; case VK_F18: key = Input::Keyboard::KeyF18; break; case VK_F19: key = Input::Keyboard::KeyF19; break; case VK_F20: key = Input::Keyboard::KeyF20; break; case VK_F21: key = Input::Keyboard::KeyF21; break; case VK_F22: key = Input::Keyboard::KeyF22; break; case VK_F23: key = Input::Keyboard::KeyF23; break; case VK_F24: key = Input::Keyboard::KeyF24; break; } if (keySym >= '0' && keySym <= '9') key = (Input::Keyboard::Key) keySym; else if (keySym >= 'A' && keySym <= 'Z') key = (Input::Keyboard::Key) keySym; return key; } S::Int S::GUI::WindowGDI::ProcessSystemMessages(UINT message, WPARAM wParam, LPARAM lParam) { /* Lock application while processing messages. */ Application::Lock lock; /* Process system messages not relevant * to portable Window implementation. */ switch (message) { case WM_CLOSE: if (doClose.Call()) Close(); return MessageProcessed; case WM_CREATE: onCreate.Emit(); return MessageProcessed; case WM_DESTROY: onDestroy.Emit(); return MessageProcessed; case WM_ACTIVATE: if (LOWORD(wParam) == WA_INACTIVE && IsWindowEnabled(hwnd)) { const WindowGDI *backend = WindowGDI::GetWindowBackend((HWND) lParam); if (backend != NIL) { if ((backend->flags & WF_TOPMOST) && (backend->flags & WF_NOTASKBUTTON) && (backend->flags & WF_THINBORDER) && backend->id > id) { PostMessage(hwnd, WM_NCACTIVATE, True, 0); } } } return MessageProcessed; case WM_ACTIVATEAPP: if (wParam == TRUE && GetForegroundWindow() == hwnd && !IsWindowEnabled(hwnd)) { /* If disabled, activate the next modal window. */ foreach (WindowGDI *backend, windowBackends) { if ( backend->hwnd != NIL && backend->id > id && (backend->flags & WF_MODAL)) { backend->Raise(); break; } } } break; case WM_SIZE: if (!minimized && wParam == SIZE_MINIMIZED) { minimized = True; onMinimize.Emit(); } else if (minimized && wParam == SIZE_RESTORED) { minimized = False; onRestore.Emit(); } break; case WM_SETTINGCHANGE: if ((wParam == SPI_SETWORKAREA) && maximized) { Rect workArea = System::Screen::GetActiveScreenWorkArea(); SetMetrics(Point(workArea.left - (frameSize.cx - 2), workArea.top - (frameSize.cy - 2)), Size(workArea.GetWidth() + (2 * frameSize.cx - 4), workArea.GetHeight() + (2 * frameSize.cy - 4)) / fontSize); } return MessageProcessed; case WM_GETMINMAXINFO: { RECT windowRect; Int windowStyle = GetWindowLong(hwnd, GWL_STYLE); LPMINMAXINFO minMaxInfo = (LPMINMAXINFO) lParam; GetWindowRect(hwnd, &windowRect); if (windowStyle & WS_DLGFRAME) { POINT maxSize = { windowRect.right - windowRect.left, windowRect.bottom - windowRect.top }; POINT maxPosition = { windowRect.left, windowRect.top }; minMaxInfo->ptMaxSize = maxSize; minMaxInfo->ptMaxPosition = maxPosition; } else { minMaxInfo->ptMinTrackSize.x = Math::Round(minSize.cx * fontSize) + sizeModifier.cx; minMaxInfo->ptMinTrackSize.y = Math::Round(minSize.cy * fontSize) + sizeModifier.cy; if (maxSize.cx > 0) minMaxInfo->ptMaxTrackSize.x = Math::Round(maxSize.cx * fontSize) + sizeModifier.cx; if (maxSize.cy > 0) minMaxInfo->ptMaxTrackSize.y = Math::Round(maxSize.cy * fontSize) + sizeModifier.cy; } } return MessageProcessed; case WM_SYSCOLORCHANGE: Backends::BackendWin32::UpdateColors(); break; case WM_IME_STARTCOMPOSITION: if (activeCursor != NIL) activeCursor->SetIMECursor(True); break; case WM_IME_ENDCOMPOSITION: if (activeCursor != NIL) activeCursor->SetIMECursor(False); break; } /* Convert Windows messages to smooth messages. */ switch (message) { /* Mouse messages: */ case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: /* Update pointer position in Input::Pointer. */ { POINT point; GetCursorPos(&point); Input::Pointer::UpdatePosition(Window::GetWindow(hwnd), point.x, point.y); } /* Register for mouse leave events. */ { TRACKMOUSEEVENT tme; tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_LEAVE; tme.hwndTrack = hwnd; tme.dwHoverTime = 0; TrackMouseEvent(&tme); } return onEvent.Call(SM_MOUSEMOVE, 0, 0); case WM_MOUSELEAVE: /* Update pointer position in Input::Pointer. */ if (IsWindowEnabled(hwnd)) { POINT point; GetCursorPos(&point); Input::Pointer::UpdatePosition(Window::GetWindow(WindowFromPoint(point)), point.x, point.y); } else { /* Clear mouse over status when being disabled. */ Input::Pointer::UpdatePosition(NIL, -1, -1); } return onEvent.Call(SM_MOUSEMOVE, 0, 0); case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_NCLBUTTONDOWN: case WM_NCRBUTTONDOWN: case WM_NCMBUTTONDOWN: case WM_NCLBUTTONUP: case WM_NCRBUTTONUP: case WM_NCMBUTTONUP: case WM_NCLBUTTONDBLCLK: case WM_NCRBUTTONDBLCLK: case WM_NCMBUTTONDBLCLK: /* Update pointer position in Input::Pointer. */ { POINT point; GetCursorPos(&point); Input::Pointer::UpdatePosition(Window::GetWindow(hwnd), point.x, point.y); } /* Receive all mouse events while button is pressed. */ if (message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN || message == WM_MBUTTONDOWN) SetCapture(hwnd); else if (message == WM_LBUTTONUP || message == WM_RBUTTONUP || message == WM_MBUTTONUP) ReleaseCapture(); /* Pass message to smooth window. */ if (message == WM_LBUTTONDOWN || message == WM_NCLBUTTONDOWN) return onEvent.Call(SM_LBUTTONDOWN, 0, 0); else if (message == WM_LBUTTONUP || message == WM_NCLBUTTONUP) return onEvent.Call(SM_LBUTTONUP, 0, 0); else if (message == WM_LBUTTONDBLCLK || message == WM_NCLBUTTONDBLCLK) return onEvent.Call(SM_LBUTTONDBLCLK, 0, 0); else if (message == WM_RBUTTONDOWN || message == WM_NCRBUTTONDOWN) return onEvent.Call(SM_RBUTTONDOWN, 0, 0); else if (message == WM_RBUTTONUP || message == WM_NCRBUTTONUP) return onEvent.Call(SM_RBUTTONUP, 0, 0); else if (message == WM_RBUTTONDBLCLK || message == WM_NCRBUTTONDBLCLK) return onEvent.Call(SM_RBUTTONDBLCLK, 0, 0); else if (message == WM_MBUTTONDOWN || message == WM_NCMBUTTONDOWN) return onEvent.Call(SM_MBUTTONDOWN, 0, 0); else if (message == WM_MBUTTONUP || message == WM_NCMBUTTONUP) return onEvent.Call(SM_MBUTTONUP, 0, 0); else if (message == WM_MBUTTONDBLCLK || message == WM_NCMBUTTONDBLCLK) return onEvent.Call(SM_MBUTTONDBLCLK, 0, 0); case WM_MOUSEWHEEL: /* Update pointer position in Input::Pointer if this is not a tool window. */ if (!((flags & WF_TOPMOST) && (flags & WF_NOTASKBUTTON) && (flags & WF_THINBORDER))) { POINT point; GetCursorPos(&point); Input::Pointer::UpdatePosition(Window::GetWindow(hwnd), point.x, point.y); } /* Pass message to smooth window. */ onEvent.Call(SM_MOUSEWHEEL, (short) HIWORD(wParam), 0); return MessageProcessed; /* Keyboard messages: */ case WM_KEYDOWN: case WM_SYSKEYDOWN: Input::Keyboard::UpdateKeyState(ConvertKey(wParam), True); return onEvent.Call(SM_KEYDOWN, ConvertKey(wParam), lParam); case WM_KEYUP: case WM_SYSKEYUP: Input::Keyboard::UpdateKeyState(ConvertKey(wParam), False); return onEvent.Call(SM_KEYUP, ConvertKey(wParam), lParam); case WM_CHAR: return onEvent.Call(SM_CHAR, wParam, lParam); /* Paint messages: */ case WM_ERASEBKGND: { static Size prevSize; RECT windowRect; GetWindowRect(hwnd, &windowRect); Size size = Size(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top); if (size.cx > prevSize.cx || size.cy > prevSize.cy) { HBRUSH brush = CreateSolidBrush(Setup::BackgroundColor); if (size.cx > prevSize.cx) { RECT rect = { prevSize.cx - 2 * frameSize.cx + 2, 0, size.cx - 2 * frameSize.cx + 2, size.cy - 2 * frameSize.cy + 2 }; FillRect((HDC) wParam, &rect, brush); } if (size.cy > prevSize.cy) { RECT rect = { 0, prevSize.cy - 2 * frameSize.cy + 2, size.cx - 2 * frameSize.cx + 2, size.cy - 2 * frameSize.cy + 2 }; FillRect((HDC) wParam, &rect, brush); } ::DeleteObject(brush); } prevSize = size; } return MessageProcessed; case WM_PAINT: { Int rVal = MessageProcessed; RECT uRect = { 0, 0, 0, 0 }; updateRect = Rect(); if (::GetUpdateRect(hwnd, &uRect, 0)) { updateRect = Rect(Point(uRect.left, uRect.top), Size(uRect.right - uRect.left, uRect.bottom - uRect.top)); updateRect = updateRect + frameSize - sizeModifier; PAINTSTRUCT ps; BeginPaint(hwnd, &ps); rVal = onEvent.Call(SM_PAINT, wParam, lParam); EndPaint(hwnd, &ps); } return rVal; } /* Window state change messages: */ case WM_WINDOWPOSCHANGED: if (!IsIconic(hwnd)) { WINDOWPOS *windowPos = (LPWINDOWPOS) lParam; if (!(windowPos->flags & SWP_NOMOVE && windowPos->flags & SWP_NOSIZE)) { Point pos = Point(windowPos->x, windowPos->y); Size size = Size(windowPos->cx, windowPos->cy) / fontSize; if (windowPos->flags & SWP_NOMOVE || windowPos->flags & SWP_NOSIZE) { RECT windowRect; GetWindowRect(hwnd, &windowRect); if (windowPos->flags & SWP_NOMOVE) pos = Point(windowRect.left, windowRect.top); else if (windowPos->flags & SWP_NOSIZE) size = Size(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top) / fontSize; } if (!(windowPos->flags & SWP_NOSIZE)) { if (drawSurface != NIL) drawSurface->SetSize(Size(windowPos->cx, windowPos->cy)); } onEvent.Call(SM_WINDOWMETRICS, ((pos.x + 32768) << 16) | (pos.y + 32768), ((size.cx + 32768) << 16) | (size.cy + 32768)); } } return MessageProcessed; case WM_SETFOCUS: return onEvent.Call(SM_GETFOCUS, 0, 0); case WM_KILLFOCUS: Input::Keyboard::ResetKeyState(); /* Release mouse capture. */ ReleaseCapture(); /* Get the window that now has the focus. */ { Window *focusWnd = Window::GetWindow((HWND) wParam); return onEvent.Call(SM_LOSEFOCUS, focusWnd != NIL ? focusWnd->GetHandle() : -1, 0); } /* Drag & drop messages: */ case WM_DROPFILES: hDrop = (HDROP) wParam; /* Compute window-relative drop position and emit event signal. * * Note that DragQueryPoint started to give incorrect values since * Windows 8 or 8.1, so we are using the mouse pointer position instead. */ { RECT windowRect; POINT cursorPos; GetWindowRect(hwnd, &windowRect); GetCursorPos(&cursorPos); onEvent.Call(SM_DROPFILES, cursorPos.x - windowRect.left, cursorPos.y - windowRect.top); } DragFinish(hDrop); hDrop = NIL; return MessageProcessed; } /* Call event for any other Windows messages. * * FixMe: Windows messages should not be propagated to smooth applications. * Define a smooth message for every Windows message we need and * replace the next line with return MessageUnknown;. * Then add a different way to pass system specific messages to the * application, like a special onSystemMessage callback. */ return onEvent.Call(message, wParam, lParam); } S::Int S::GUI::WindowGDI::Open(const String &title, const Point &pos, const Size &size, Int iFlags) { flags = iFlags; Int style = WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_POPUP; Int extStyle = 0; if (flags & WF_NORESIZE ) { style ^= WS_THICKFRAME; style |= WS_DLGFRAME; } if (flags & WF_THINBORDER ) style ^= WS_THICKFRAME | WS_SYSMENU; if (flags & WF_TOPMOST ) extStyle |= WS_EX_TOPMOST; if (flags & WF_NOTASKBUTTON) extStyle |= WS_EX_TOOLWINDOW; wndclass = new WNDCLASSEX; wndclass->cbSize = sizeof(WNDCLASSEX); wndclass->style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; /* Enable shadows for tool windows. */ if ((flags & WF_TOPMOST) && (flags & WF_NOTASKBUTTON) && (flags & WF_THINBORDER)) { if (Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 5, 1)) wndclass->style = wndclass->style | CS_DROPSHADOW; } wndclass->lpfnWndProc = WindowProc; wndclass->cbClsExtra = 0; wndclass->cbWndExtra = 0; wndclass->hInstance = hDllInstance; wndclass->hIcon = sysIcon; wndclass->hCursor = LoadCursor(NIL, MAKEINTRESOURCE(32512)); wndclass->hbrBackground = NIL; wndclass->lpszMenuName = NIL; wndclass->lpszClassName = className; wndclass->hIconSm = sysIcon; RegisterClassEx(wndclass); hwnd = CreateWindowEx(extStyle, className, title, style, pos.x, pos.y, Math::Round(size.cx * fontSize) + sizeModifier.cx, Math::Round(size.cy * fontSize) + sizeModifier.cy, NIL, NIL, hDllInstance, NIL); if (hwnd != NIL) { /* Process the WM_CREATE message again, as GetWindowBackend * cannot find the correct backend until hwnd is set. */ ProcessSystemMessages(WM_CREATE, 0, 0); if ((flags & WF_THINBORDER) || (flags & WF_NORESIZE)) drawSurface = new Surface(hwnd, size * fontSize + sizeModifier); else drawSurface = new Surface(hwnd); drawSurface->SetSize(size * fontSize + sizeModifier); /* Control top edge color on Windows 10 and 11. */ if (ex_DwmSetWindowAttribute != NIL) { /* Set dark top edge if we are in dark mode. */ if (Setup::BackgroundColor.ConvertTo(Color::GRAY) <= 127) { BOOL darkMode = TRUE; ex_DwmSetWindowAttribute(hwnd, /* DWMWA_USE_IMMERSIVE_DARK_MODE */ 20, &darkMode, sizeof(darkMode)); } /* Set top edge to background color (Windows 11 only). */ COLORREF captionColor = Setup::BackgroundColor.GetBlue() << 16 | Setup::BackgroundColor.GetGreen() << 8 | Setup::BackgroundColor.GetRed(); ex_DwmSetWindowAttribute(hwnd, /* DWMWA_CAPTION_COLOR */ 35, &captionColor, sizeof(captionColor)); } /* Disable leader window if we are modal. */ if (flags & WF_MODAL) { WindowGDI *leader = FindLeaderWindow(); if (leader != NIL) { /* If the leader window belongs to another thread, * we need to suspend our application lock in order * for EnableWindow to finish. */ Int suspendCount = (GetWindowThreadProcessId(leader->hwnd, NIL) != GetCurrentThreadId() ? Application::Lock::SuspendLock() : 0); /* Now disable the leader window. */ EnableWindow(leader->hwnd, False); /* Resume the application lock. */ Application::Lock::ResumeLock(suspendCount); /* Raise our new window. */ Raise(); } } /* Enable dropping files if requested. */ if (enableDropFiles) EnableDropFiles(True); return Success(); } return Error(); } S::Int S::GUI::WindowGDI::Close() { if (hwnd == NIL) return Success(); /* Reenable leader window if we have one. */ if (flags & WF_MODAL) { WindowGDI *leader = FindLeaderWindow(); if (leader != NIL) { /* If the leader window belongs to another thread, * we need to suspend our application lock in order * for EnableWindow to finish. */ Int suspendCount = (GetWindowThreadProcessId(leader->hwnd, NIL) != GetCurrentThreadId() ? Application::Lock::SuspendLock() : 0); /* Now enable the leader window. */ EnableWindow(leader->hwnd, True); /* Resume the application lock. */ Application::Lock::ResumeLock(suspendCount); /* Raise the leader window. */ leader->Raise(); } } /* Delete surface. */ if (drawSurface != NIL) delete drawSurface; drawSurface = NIL; /* Destroy window and unregister class. */ DestroyWindow(hwnd); UnregisterClass(className, hDllInstance); delete wndclass; wndclass = NIL; return Success(); } S::Int S::GUI::WindowGDI::RequestClose() { if (GetWindowThreadProcessId(hwnd, NIL) != GetCurrentThreadId()) PostMessage(hwnd, WM_CLOSE, 0, 0); else SendMessage(hwnd, WM_CLOSE, 0, 0); return Success(); } S::GUI::WindowGDI *S::GUI::WindowGDI::FindLeaderWindow() { /* The leader window is the newest non topmost window. */ foreachreverse (WindowGDI *backend, windowBackends) { if ( backend->id < id && backend->hwnd != NIL && !(backend->flags & WF_TOPMOST)) return backend; } return NIL; } S::Int S::GUI::WindowGDI::SetTitle(const String &nTitle) { if (hwnd == NIL) return Error(); SetWindowText(hwnd, nTitle); return Success(); } S::Int S::GUI::WindowGDI::SetIcon(const Bitmap &newIcon) { if (destroyIcon) DestroyIcon(sysIcon); /* Scale to standard icon size. */ Size iconSize = Size(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); Bitmap iconScaled = newIcon.Scale(iconSize); /* Set up alpha mask. */ Bitmap iconMask = iconScaled; Int depth = iconScaled.GetDepth(); Int transparentPixel = 16777215; for (Int y = 0; y < iconSize.cy; y++) { for (Int x = 0; x < iconSize.cx; x++) { Color pixel = iconScaled.GetPixel(Point(x, y)); if (depth == 32) iconMask.SetPixel(Point(x, y), pixel.GetAlpha() >= 128 ? transparentPixel : 0); else iconMask.SetPixel(Point(x, y), pixel == Color(192, 192, 192) ? transparentPixel : 0); } } /* Create icon. */ ICONINFO icon; icon.fIcon = true; icon.xHotspot = 0; icon.yHotspot = 0; icon.hbmMask = (HBITMAP) iconMask.GetSystemBitmap(); icon.hbmColor = (HBITMAP) iconScaled.GetSystemBitmap(); sysIcon = CreateIconIndirect(&icon); destroyIcon = True; return Success(); } S::Int S::GUI::WindowGDI::SetIconDirect(Void *newIcon) { if (destroyIcon) DestroyIcon(sysIcon); sysIcon = (HICON) newIcon; destroyIcon = False; return Success(); } S::Int S::GUI::WindowGDI::EnableDropFiles(Bool nEnableDropFiles) { enableDropFiles = nEnableDropFiles; if (hwnd == NIL) return Success(); /* If the window belongs to another thread, we * need to suspend our application lock in order * for DragAcceptFiles to finish. */ Int suspendCount = (GetWindowThreadProcessId(hwnd, NIL) != GetCurrentThreadId() ? Application::Lock::SuspendLock() : 0); DragAcceptFiles(hwnd, enableDropFiles); if (enableDropFiles && dropTarget == NIL) { dropTarget = new DropTarget(this); RegisterDragDrop(hwnd, dropTarget); } else if (!enableDropFiles && dropTarget != NIL) { RevokeDragDrop(hwnd); dropTarget->Release(); dropTarget = NIL; } /* Resume the application lock. */ Application::Lock::ResumeLock(suspendCount); return Success(); } const S::Array &S::GUI::WindowGDI::GetDroppedFiles() const { if (hDrop == NIL && dropTarget == NIL) return WindowBackend::GetDroppedFiles(); static Array fileNames; fileNames.RemoveAll(); if (hDrop == NIL) { /* Query files from drop target. */ const Array &files = ((DropTarget *) dropTarget)->GetDroppedFiles(); foreach (const String &file, files) fileNames.Add(file); } else { fileNames = DropTarget::GetFilesFromHDROP(hDrop); } return fileNames; } S::Int S::GUI::WindowGDI::SetMinimumSize(const Size &nMinSize) { minSize = nMinSize; if (hwnd == NIL) return Success(); RECT windowRect; GetWindowRect(hwnd, &windowRect); SetMetrics(Point(windowRect.left, windowRect.top), Size(Math::Max(Math::Round((windowRect.right - windowRect.left - sizeModifier.cx) / fontSize), minSize.cx), Math::Max(Math::Round((windowRect.bottom - windowRect.top - sizeModifier.cy) / fontSize), minSize.cy))); return Success(); } S::Int S::GUI::WindowGDI::SetMaximumSize(const Size &nMaxSize) { maxSize = nMaxSize; if (hwnd == NIL) return Success(); RECT windowRect; GetWindowRect(hwnd, &windowRect); SetMetrics(Point(windowRect.left, windowRect.top), Size(Math::Min(Math::Round((windowRect.right - windowRect.left - sizeModifier.cx) / fontSize), maxSize.cx), Math::Min(Math::Round((windowRect.bottom - windowRect.top - sizeModifier.cy) / fontSize), maxSize.cy))); return Success(); } S::Int S::GUI::WindowGDI::Show() { if (hwnd == NIL) return Success(); if (GetWindowThreadProcessId(hwnd, NIL) != GetCurrentThreadId()) ShowWindowAsync(hwnd, SW_SHOW); else ShowWindow(hwnd, SW_SHOW); return Success(); } S::Int S::GUI::WindowGDI::Hide() { if (hwnd == NIL) return Success(); if (GetWindowThreadProcessId(hwnd, NIL) != GetCurrentThreadId()) ShowWindowAsync(hwnd, SW_HIDE); else ShowWindow(hwnd, SW_HIDE); return Success(); } S::Int S::GUI::WindowGDI::SetMetrics(const Point &nPos, const Size &nSize) { if (hwnd == NIL) return Success(); SetWindowPos(hwnd, 0, nPos.x, nPos.y, Math::Round(nSize.cx * fontSize) + sizeModifier.cx, Math::Round(nSize.cy * fontSize) + sizeModifier.cy, SWP_NOZORDER | SWP_ASYNCWINDOWPOS); return Success(); } S::Int S::GUI::WindowGDI::Minimize() { if (hwnd == NIL) return Success(); if (GetWindowThreadProcessId(hwnd, NIL) != GetCurrentThreadId()) ShowWindowAsync(hwnd, SW_MINIMIZE); else ShowWindow(hwnd, SW_MINIMIZE); return Success(); } S::Int S::GUI::WindowGDI::Maximize() { if (hwnd == NIL) return Success(); Rect workArea = System::Screen::GetActiveScreenWorkArea(); { RECT rect; GetWindowRect(hwnd, &rect); restoredRect = Rect(Point(rect.left, rect.top), (Size(rect.right - rect.left, rect.bottom - rect.top) - sizeModifier) / fontSize); } restoredWndStyle = GetWindowLong(hwnd, GWL_STYLE); SetWindowLong(hwnd, GWL_STYLE, restoredWndStyle ^ (WS_THICKFRAME | WS_SYSMENU)); SetMetrics(Point(workArea.left - (frameSize.cx - 1), workArea.top - (frameSize.cy - 1)), (Size(workArea.GetWidth() + (2 * frameSize.cx - 2), workArea.GetHeight() + (2 * frameSize.cy - 2)) - sizeModifier) / fontSize); maximized = True; onMaximize.Emit(); return Success(); } S::Int S::GUI::WindowGDI::Restore() { if (hwnd == NIL) return Success(); SetWindowLong(hwnd, GWL_STYLE, restoredWndStyle | WS_VISIBLE); SetMetrics(Point(restoredRect.left, restoredRect.top), Size((Int) Math::Max(minSize.cx, restoredRect.GetWidth()), (Int) Math::Max(minSize.cy, restoredRect.GetHeight()))); maximized = False; onRestore.Emit(); return Success(); } S::Int S::GUI::WindowGDI::Raise() { if (hwnd == NIL) return Success(); SetForegroundWindow(hwnd); SetFocus(hwnd); return Success(); } S::Int S::GUI::WindowGDI::SetProgressIndicator(Window::ProgressIndicatorState state, Float value) { HRESULT hr = S_OK; if (taskbar == NIL) hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, IID_ITaskbarList3, (void **) &taskbar); if (hr != S_OK) return Error(); switch (state) { case Window::ProgressIndicatorNone: taskbar->SetProgressState(hwnd, TBPF_NOPROGRESS); break; case Window::ProgressIndicatorNormal: taskbar->SetProgressState(hwnd, TBPF_NORMAL); if (value >= 0) taskbar->SetProgressValue(hwnd, Math::Round(value * 10.0), 1000); break; case Window::ProgressIndicatorPaused: taskbar->SetProgressState(hwnd, TBPF_PAUSED); if (value >= 0) taskbar->SetProgressValue(hwnd, Math::Round(value * 10.0), 1000); break; } return Success(); } S::Void S::GUI::WindowGDI::SetCursor(Cursor *cursor, const Point &point) { Window *window = cursor->GetContainerWindow(); HWND hwnd = (HWND) window->GetSystemWindow(); HIMC himc = ImmGetContext(hwnd); /* Clear composition string. */ if (cursor != activeCursor) ImmSetCompositionString(himc, SCS_SETSTR, NIL, 0, NIL, 0); /* Set composition window information. */ COMPOSITIONFORM info; info.dwStyle = CFS_DEFAULT; ImmSetCompositionWindow(himc, &info); info.dwStyle = CFS_POINT; info.ptCurrentPos.x = point.x - GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXPADDEDBORDER); info.ptCurrentPos.y = point.y - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CXPADDEDBORDER); if (window->GetFlags() & WF_NORESIZE) { info.ptCurrentPos.x = point.x - GetSystemMetrics(SM_CXDLGFRAME) - 1; info.ptCurrentPos.y = point.y - GetSystemMetrics(SM_CYDLGFRAME) - 1; } ImmSetCompositionWindow(himc, &info); /* Set font information. */ LOGFONT lFont; const Font &font = cursor->GetFont(); int nameLength = Math::Min(font.GetName().Length() + 1, LF_FACESIZE); lFont.lfHeight = -Math::Round(font.GetSize() * 128.0 / Surface().GetSurfaceDPI()); lFont.lfWidth = 0; lFont.lfEscapement = 0; lFont.lfOrientation = 0; lFont.lfWeight = (font.GetWeight() >= Font::Bold) ? FW_BOLD : FW_NORMAL; lFont.lfItalic = (font.GetStyle() & Font::Italic) ? true : false; lFont.lfUnderline = (font.GetStyle() & Font::Underline) ? true : false; lFont.lfStrikeOut = (font.GetStyle() & Font::StrikeOut) ? true : false; lFont.lfOutPrecision = OUT_DEFAULT_PRECIS; lFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; lFont.lfCharSet = DEFAULT_CHARSET; lFont.lfQuality = DEFAULT_QUALITY; lFont.lfPitchAndFamily = DEFAULT_PITCH | FF_ROMAN; memcpy(lFont.lfFaceName, (wchar_t *) font.GetName(), sizeof(wchar_t) * nameLength); lFont.lfFaceName[nameLength - 1] = 0; ImmSetCompositionFont(himc, &lFont); ImmReleaseContext(hwnd, himc); activeCursor = cursor; } S::Void S::GUI::WindowGDI::RemoveCursor(Cursor *cursor) { if (activeCursor != cursor) return; HWND hwnd = (HWND) cursor->GetContainerWindow()->GetSystemWindow(); HIMC himc = ImmGetContext(hwnd); /* Clear composition string. */ ImmSetCompositionString(himc, SCS_SETSTR, NIL, 0, NIL, 0); /* Revert to default composition window. */ COMPOSITIONFORM info; info.dwStyle = CFS_DEFAULT; ImmSetCompositionWindow(himc, &info); ImmSetCompositionWindow(himc, &info); ImmReleaseContext(hwnd, himc); activeCursor = NIL; } smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/haiku/000077500000000000000000000000001516402577000243635ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/haiku/Makefile000066400000000000000000000006561516402577000260320ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_HAIKU),True) OBJECTS += windowhaiku.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/haiku/windowhaiku.cpp000066400000000000000000000502771516402577000274330ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include S::GUI::WindowBackend *CreateWindowHaiku() { return new S::GUI::WindowHaiku(); } S::Int windowHaikuTmp = S::GUI::WindowBackend::SetBackend(&CreateWindowHaiku); S::Array S::GUI::WindowHaiku::windowBackends; namespace smooth { namespace GUI { const Int B_WINDOW_CREATED = 'WCRE'; const Int B_WINDOW_DESTROYED = 'WDES'; const Int B_PAINT = 'PINT'; class HaikuView : public BView { public: HaikuView(BRect frame) : BView(frame, NULL, B_FOLLOW_ALL_SIDES, B_WILL_DRAW) { SetEventMask(B_POINTER_EVENTS); SetViewColor(Setup::BackgroundColor.GetRed(), Setup::BackgroundColor.GetGreen(), Setup::BackgroundColor.GetBlue()); } void Draw(BRect updateRect) { BWindow *wnd = Window(); WindowHaiku *backend = WindowHaiku::GetWindowBackend(wnd); backend->ProcessSystemMessages(B_PAINT, (((int) updateRect.left + 32768) << 16) | ((int) updateRect.top + 32768), (((int) updateRect.Width() + 32768) << 16) | ((int) updateRect.Height() + 32768), *(wnd->CurrentMessage())); } void MouseMoved(BPoint point, uint32 transit, const BMessage *message) { BWindow *wnd = Window(); BPoint pos = wnd->ConvertToScreen(point); if (transit == B_ENTERED_VIEW || transit == B_INSIDE_VIEW) Input::Pointer::UpdatePosition(Window::GetWindow(wnd), pos.x, pos.y); else if (transit == B_EXITED_VIEW) Input::Pointer::UpdatePosition(NIL, pos.x, pos.y); else if (transit == B_OUTSIDE_VIEW) Input::Pointer::UpdatePosition(Input::Pointer::GetPointerWindow(), pos.x, pos.y); System::EventHaiku::EnqueueMessage(wnd, *(wnd->CurrentMessage()), B_MOUSE_MOVED, point.x, point.y); } void MouseDown(BPoint point) { BWindow *wnd = Window(); if (Input::Pointer::GetPointerWindow() != Window::GetWindow(wnd)) return; System::EventHaiku::EnqueueMessage(wnd, *(wnd->CurrentMessage()), B_MOUSE_DOWN, point.x, point.y); } void MouseUp(BPoint point) { BWindow *wnd = Window(); System::EventHaiku::EnqueueMessage(wnd, *(wnd->CurrentMessage()), B_MOUSE_UP, point.x, point.y); } }; class HaikuWindow : public BWindow { private: BView *view; public: HaikuWindow(BRect frame, String title, Int look, Int feel, S::Int flags) : BWindow(frame, title, (window_look) look, (window_feel) feel, flags) { view = new HaikuView(Bounds()); AddChild(view); } void WindowActivated(bool active) { System::EventHaiku::EnqueueMessage(this, *CurrentMessage(), B_WINDOW_ACTIVATED, active, 0); } void FrameMoved(BPoint origin) { WindowHaiku *backend = WindowHaiku::GetWindowBackend(this); backend->ProcessSystemMessages(B_WINDOW_MOVED, origin.x, origin.y, *CurrentMessage()); } void FrameResized(float width, float height) { WindowHaiku *backend = WindowHaiku::GetWindowBackend(this); backend->ProcessSystemMessages(B_WINDOW_RESIZED, width, height, *CurrentMessage()); } bool QuitRequested() { WindowHaiku *backend = WindowHaiku::GetWindowBackend(this); backend->RequestClose(); if (backend->GetSystemWindow() == NIL) return true; else return false; } void MessageReceived(BMessage *message) { System::EventHaiku::EnqueueMessage(this, *CurrentMessage(), message->what, 0, 0); if (message->what != B_SIMPLE_DATA) BWindow::MessageReceived(message); } }; }; }; S::GUI::WindowHaiku::WindowHaiku(Void *iWindow) { type = WINDOW_HAIKU; wnd = NIL; view = NIL; id = windowBackends.Add(this); minSize = Size(160, 24); maxSize = Size(32768, 32768); fontSize = Surface().GetSurfaceDPI() / 96.0; flags = 0; dropMessage = NIL; } S::GUI::WindowHaiku::~WindowHaiku() { windowBackends.Remove(id); } S::Void *S::GUI::WindowHaiku::GetSystemWindow() const { return (Void *) wnd; } S::GUI::WindowHaiku *S::GUI::WindowHaiku::GetWindowBackend(BWindow *wnd) { if (wnd == NIL) return NIL; for (Int i = 0; i < windowBackends.Length(); i++) { WindowHaiku *window = windowBackends.GetNth(i); if (window != NIL) { if (window->wnd == wnd) return window; } } return NIL; } S::Input::Keyboard::Key S::GUI::WindowHaiku::ConvertKey(Int keyCode, const BMessage ¤tMessage) { Input::Keyboard::Key key = Input::Keyboard::KeyOther; switch (keyCode) { case B_LEFT_ARROW: key = Input::Keyboard::KeyLeft; break; case B_UP_ARROW: key = Input::Keyboard::KeyUp; break; case B_RIGHT_ARROW: key = Input::Keyboard::KeyRight; break; case B_DOWN_ARROW: key = Input::Keyboard::KeyDown; break; case B_HOME: key = Input::Keyboard::KeyHome; break; case B_END: key = Input::Keyboard::KeyEnd; break; case B_INSERT: key = Input::Keyboard::KeyInsert; break; case B_DELETE: key = Input::Keyboard::KeyDelete; break; case B_PAGE_UP: key = Input::Keyboard::KeyPrior; break; case B_PAGE_DOWN: key = Input::Keyboard::KeyNext; break; case B_RETURN: key = Input::Keyboard::KeyReturn; break; case B_BACKSPACE: key = Input::Keyboard::KeyBack; break; case B_TAB: key = Input::Keyboard::KeyTab; break; case B_SPACE: key = Input::Keyboard::KeySpace; break; case B_ESCAPE: key = Input::Keyboard::KeyEscape; break; case B_FUNCTION_KEY: { int32 keyCode; currentMessage.FindInt32("key", &keyCode); switch (keyCode) { case B_F1_KEY: key = Input::Keyboard::KeyF1; break; case B_F2_KEY: key = Input::Keyboard::KeyF2; break; case B_F3_KEY: key = Input::Keyboard::KeyF3; break; case B_F4_KEY: key = Input::Keyboard::KeyF4; break; case B_F5_KEY: key = Input::Keyboard::KeyF5; break; case B_F6_KEY: key = Input::Keyboard::KeyF6; break; case B_F7_KEY: key = Input::Keyboard::KeyF7; break; case B_F8_KEY: key = Input::Keyboard::KeyF8; break; case B_F9_KEY: key = Input::Keyboard::KeyF9; break; case B_F10_KEY: key = Input::Keyboard::KeyF10; break; case B_F11_KEY: key = Input::Keyboard::KeyF11; break; case B_F12_KEY: key = Input::Keyboard::KeyF12; break; } } } if (keyCode >= '0' && keyCode <= '9') key = (Input::Keyboard::Key) keyCode; else if (keyCode >= 'a' && keyCode <= 'z') key = (Input::Keyboard::Key) (keyCode - 0x20); return key; } S::Int S::GUI::WindowHaiku::ProcessSystemMessages(Int message, Int wParam, Int lParam, const BMessage ¤tMessage) { static Int focusWndId = -1; /* Lock application while processing messages. */ Application::Lock lock; /* Process system messages not relevant * to portable Window implementation. */ switch (message) { case B_WINDOW_CREATED: onCreate.Emit(); /* Set internal focus window. */ focusWndId = id; onEvent.Call(SM_GETFOCUS, 0, 0); return MessageProcessed; case B_WINDOW_DESTROYED: onDestroy.Emit(); /* Clear internal focus window. */ if (focusWndId == id) focusWndId = -1; return MessageProcessed; } static int32 buttons = -1; int32 clicks = 0; float amount = 0; /* Convert Windows messages to smooth messages. */ switch (message) { /* Mouse messages: */ case B_MOUSE_MOVED: return onEvent.Call(SM_MOUSEMOVE, 0, 0); case B_MOUSE_WHEEL_CHANGED: currentMessage.FindFloat("be:wheel_delta_y", &amount); /* Pass message to smooth window. */ onEvent.Call(SM_MOUSEWHEEL, amount * -120.0, 0); break; case B_MOUSE_DOWN: currentMessage.FindInt32("buttons", &buttons); currentMessage.FindInt32("clicks", &clicks); /* Reject if a modal window is active. */ if (IsModalWindowActive()) break; /* Grab the keyboard focus if we don't have it already. */ if (focusWndId != id) { WindowHaiku *focusWnd = windowBackends.Get(focusWndId); if (focusWnd != NIL) focusWnd->onEvent.Call(SM_LOSEFOCUS, Window::GetWindow((Void *) wnd)->GetHandle(), 0); focusWndId = id; onEvent.Call(SM_GETFOCUS, 0, 0); } /* Send mouse button event. */ if (buttons == B_PRIMARY_MOUSE_BUTTON) onEvent.Call(SM_LBUTTONDOWN, 0, 0); else if (buttons == B_SECONDARY_MOUSE_BUTTON) onEvent.Call(SM_RBUTTONDOWN, 0, 0); else if (buttons == B_TERTIARY_MOUSE_BUTTON) onEvent.Call(SM_MBUTTONDOWN, 0, 0); if (clicks == 2) { if (buttons == B_PRIMARY_MOUSE_BUTTON) onEvent.Call(SM_LBUTTONDBLCLK, 0, 0); else if (buttons == B_SECONDARY_MOUSE_BUTTON) onEvent.Call(SM_RBUTTONDBLCLK, 0, 0); else if (buttons == B_TERTIARY_MOUSE_BUTTON) onEvent.Call(SM_MBUTTONDBLCLK, 0, 0); } break; case B_MOUSE_UP: /* Send mouse button event. */ if (buttons == B_PRIMARY_MOUSE_BUTTON) onEvent.Call(SM_LBUTTONUP, 0, 0); else if (buttons == B_SECONDARY_MOUSE_BUTTON) onEvent.Call(SM_RBUTTONUP, 0, 0); else if (buttons == B_TERTIARY_MOUSE_BUTTON) onEvent.Call(SM_MBUTTONUP, 0, 0); break; /* Keyboard messages: */ case B_KEY_DOWN: { int32 raw = 0; const char *bytes = NIL; String string; currentMessage.FindInt32("raw_char", &raw); currentMessage.FindString("bytes", &bytes); string.ImportFrom("UTF-8", bytes); onEvent.Call(SM_CHAR, string[0], 0); Input::Keyboard::UpdateKeyState(ConvertKey(raw, currentMessage), True); onEvent.Call(SM_KEYDOWN, ConvertKey(raw, currentMessage), 0); } break; case B_KEY_UP: { int32 raw = 0; currentMessage.FindInt32("raw_char", &raw); Input::Keyboard::UpdateKeyState(ConvertKey(raw, currentMessage), False); onEvent.Call(SM_KEYUP, ConvertKey(raw, currentMessage), 0); } break; case B_MODIFIERS_CHANGED: { int32 modifiers = 0; currentMessage.FindInt32("modifiers", &modifiers); Input::Keyboard::UpdateKeyState(Input::Keyboard::KeyShift, modifiers & B_SHIFT_KEY); Input::Keyboard::UpdateKeyState(Input::Keyboard::KeyControl, modifiers & B_CONTROL_KEY); Input::Keyboard::UpdateKeyState(Input::Keyboard::KeyAlt, modifiers & B_COMMAND_KEY); if (modifiers & B_SHIFT_KEY) onEvent.Call(SM_KEYDOWN, Input::Keyboard::KeyShift, 0); if (modifiers & B_CONTROL_KEY) onEvent.Call(SM_KEYDOWN, Input::Keyboard::KeyControl, 0); if (modifiers & B_COMMAND_KEY) onEvent.Call(SM_KEYDOWN, Input::Keyboard::KeyAlt, 0); } break; /* Clipboard messages: */ case B_COPY: onEvent.Call(SM_KEYDOWN, 'C', 0); break; case B_CUT: onEvent.Call(SM_KEYDOWN, 'X', 0); break; case B_PASTE: onEvent.Call(SM_KEYDOWN, 'V', 0); break; case B_SELECT_ALL: onEvent.Call(SM_KEYDOWN, 'A', 0); break; case B_UNDO: onEvent.Call(SM_KEYDOWN, 'Z', 0); break; case B_REDO: onEvent.Call(SM_KEYDOWN, 'Y', 0); break; /* Paint messages: */ case B_PAINT: { BRect windowRect = wnd->Frame(); Point pos = Point(windowRect.left, windowRect.top); Size size = (Size(windowRect.Width(), windowRect.Height()) + Size(1, 1)) / fontSize; if (drawSurface != NIL) drawSurface->SetSize(Size(windowRect.Width(), windowRect.Height()) + Size(1, 1)); onEvent.Call(SM_WINDOWMETRICS, ((pos.x + 32768) << 16) | (pos.y + 32768), ((size.cx + 32768) << 16) | (size.cy + 32768)); updateRect = Rect(Point((unsigned(wParam) >> 16) - 32768, (unsigned(wParam) & 65535) - 32768), Size((unsigned(lParam) >> 16) - 32768, (unsigned(lParam) & 65535) - 32768) + Size(1, 1)); onEvent.Call(SM_PAINT, 0, 0); } break; /* Window state change messages: */ case B_WINDOW_RESIZED: { BRect windowRect = wnd->Frame(); Point pos = Point(windowRect.left, windowRect.top); Size size = (Size(windowRect.Width(), windowRect.Height()) + Size(1, 1)) / fontSize; if (drawSurface != NIL) drawSurface->SetSize(Size(windowRect.Width(), windowRect.Height()) + Size(1, 1)); onEvent.Call(SM_WINDOWMETRICS, ((pos.x + 32768) << 16) | (pos.y + 32768), ((size.cx + 32768) << 16) | (size.cy + 32768)); updateRect = Rect(Point(0, 0), Size(windowRect.Width(), windowRect.Height()) + Size(1, 1)); onEvent.Call(SM_PAINT, 0, 0); } break; case B_WINDOW_MOVED: { BRect windowRect = wnd->Frame(); Point pos = Point(windowRect.left, windowRect.top); Size size = (Size(windowRect.Width(), windowRect.Height()) + Size(1, 1)) / fontSize; onEvent.Call(SM_WINDOWMETRICS, ((pos.x + 32768) << 16) | (pos.y + 32768), ((size.cx + 32768) << 16) | (size.cy + 32768)); } return Success(); case B_WINDOW_ACTIVATED: if (wParam == True) { focusWndId = id; onEvent.Call(SM_GETFOCUS, 0, 0); } else { Input::Keyboard::ResetKeyState(); System::System::Sleep(50); /* Get the window that now has the focus. */ Window *focusWnd = NIL; foreach (WindowHaiku *backend, windowBackends) { if (backend->wnd != NIL && backend->wnd->IsActive()) { focusWnd = Window::GetWindow((Void *) backend->wnd); break; } } onEvent.Call(SM_LOSEFOCUS, focusWnd != NIL ? focusWnd->GetHandle() : -1, 0); } break; /* Drag & drop messages: */ case B_SIMPLE_DATA: { BPoint cursorPos; currentMessage.FindPoint("_drop_point_", &cursorPos); cursorPos = wnd->ConvertFromScreen(cursorPos); dropMessage = ¤tMessage; onEvent.Call(SM_DROPFILES, cursorPos.x, cursorPos.y); } break; } return Success(); } S::Int S::GUI::WindowHaiku::Open(const String &title, const Point &pos, const Size &size, Int iFlags) { flags = iFlags; Int windowLook = B_TITLED_WINDOW_LOOK; Int windowFeel = B_NORMAL_WINDOW_FEEL; Int windowFlags = 0; if (flags & WF_NORESIZE ) windowFlags |= B_NOT_RESIZABLE; if (flags & WF_NOTITLE ) windowLook ^= B_TITLED_WINDOW_LOOK; if (flags & WF_THINBORDER) { windowFlags = B_AVOID_FOCUS; windowLook = B_NO_BORDER_WINDOW_LOOK; } if (flags & WF_TOPMOST ) windowFeel = B_FLOATING_ALL_WINDOW_FEEL; if (flags & WF_MODAL ) windowFeel = B_MODAL_APP_WINDOW_FEEL; wnd = new HaikuWindow(BRect(pos.x, pos.y, pos.x + Math::Round(size.cx * fontSize) + sizeModifier.cx - 1, pos.y + Math::Round(size.cy * fontSize) + sizeModifier.cy - 1), title, windowLook, windowFeel, windowFlags); if (wnd != NIL) { view = wnd->ChildAt(0); /* Send the Create message. */ ProcessSystemMessages(B_WINDOW_CREATED, 0, 0, BMessage()); /* Create drawing surface. */ if ((flags & WF_THINBORDER) || (flags & WF_NORESIZE)) drawSurface = new Surface(view, size * fontSize + sizeModifier); else drawSurface = new Surface(view); drawSurface->SetSize(size * fontSize + sizeModifier); /* Set minimum and maximum size. */ if (!(flags & WF_NORESIZE || flags & WF_THINBORDER)) wnd->SetSizeLimits(Math::Round(minSize.cx * fontSize) + sizeModifier.cx - 1, Math::Round(maxSize.cx * fontSize) + sizeModifier.cx - 1, Math::Round(minSize.cy * fontSize) + sizeModifier.cy - 1, Math::Round(maxSize.cy * fontSize) + sizeModifier.cy - 1); return Success(); } return Error(); } S::Int S::GUI::WindowHaiku::Close() { if (wnd == NIL) return Success(); /* Send the Destroy message. */ ProcessSystemMessages(B_WINDOW_DESTROYED, 0, 0, BMessage()); if (Window::nOfActiveWindows == 0) { BApplication *app = Backends::BackendHaiku::GetApplication(); app->PostMessage(B_QUIT_REQUESTED); } /* Suspend the application lock to * allow the quit operation to finish. */ Int suspendCount = (wnd->Thread() != find_thread(NIL) ? Application::Lock::SuspendLock() : 0); /* Destroy window. */ BWindow *oldwnd = wnd; oldwnd->Lock(); wnd = NIL; view = NIL; oldwnd->Quit(); /* Resume the application lock. */ Application::Lock::ResumeLock(suspendCount); /* Delete surface. */ if (drawSurface != NIL) delete drawSurface; drawSurface = NIL; return Success(); } S::Int S::GUI::WindowHaiku::RequestClose() { if (doClose.Call()) return Close(); return Success(); } S::Bool S::GUI::WindowHaiku::IsModalWindowActive() { /* Ignore modal windows if this is a topmost window. */ if (flags & WF_TOPMOST) return False; /* Look for modal windows opened after ourselves. */ foreachreverse (WindowHaiku *backend, windowBackends) { if (backend == this) return False; else if (backend->wnd != NIL && backend->flags & WF_MODAL) return True; } return False; } S::Int S::GUI::WindowHaiku::SetTitle(const String &nTitle) { if (wnd == NIL) return Error(); wnd->SetTitle(nTitle); return Success(); } const S::Array &S::GUI::WindowHaiku::GetDroppedFiles() const { if (dropMessage == NIL) return WindowBackend::GetDroppedFiles(); static Array fileNames; fileNames.RemoveAll(); /* Query number of files dropped. */ int32 nOfFiles = 0; dropMessage->GetInfo("refs", NIL, &nOfFiles); /* Query dropped files. */ for (Int i = 0; i < nOfFiles; i++) { entry_ref ref; BPath path; dropMessage->FindRef("refs", i, &ref); BEntry(&ref).GetPath(&path); fileNames.Add(path.Path()); } return fileNames; } S::Int S::GUI::WindowHaiku::SetMinimumSize(const Size &nMinSize) { minSize = nMinSize; if (wnd == NIL) return Success(); wnd->SetSizeLimits(Math::Round(minSize.cx * fontSize) + sizeModifier.cx - 1, Math::Round(maxSize.cx * fontSize) + sizeModifier.cx - 1, Math::Round(minSize.cy * fontSize) + sizeModifier.cy - 1, Math::Round(maxSize.cy * fontSize) + sizeModifier.cy - 1); BRect windowRect = wnd->Frame(); SetMetrics(Point(windowRect.left, windowRect.top), Size(Math::Max(Math::Round((windowRect.right - windowRect.left - sizeModifier.cx + 1) / fontSize), minSize.cx), Math::Max(Math::Round((windowRect.bottom - windowRect.top - sizeModifier.cy + 1) / fontSize), minSize.cy))); return Success(); } S::Int S::GUI::WindowHaiku::SetMaximumSize(const Size &nMaxSize) { maxSize = nMaxSize; if (wnd == NIL) return Success(); wnd->SetSizeLimits(Math::Round(minSize.cx * fontSize) + sizeModifier.cx - 1, Math::Round(maxSize.cx * fontSize) + sizeModifier.cx - 1, Math::Round(minSize.cy * fontSize) + sizeModifier.cy - 1, Math::Round(maxSize.cy * fontSize) + sizeModifier.cy - 1); BRect windowRect = wnd->Frame(); SetMetrics(Point(windowRect.left, windowRect.top), Size(Math::Min(Math::Round((windowRect.right - windowRect.left - sizeModifier.cx + 1) / fontSize), maxSize.cx), Math::Min(Math::Round((windowRect.bottom - windowRect.top - sizeModifier.cy + 1) / fontSize), maxSize.cy))); return Success(); } S::Int S::GUI::WindowHaiku::Show() { if (wnd == NIL) return Success(); if (wnd->IsHidden()) { while (wnd->LockWithTimeout(0) != B_OK) Application::Lock::ResumeLock(Application::Lock::SuspendLock()); wnd->Show(); wnd->Unlock(); } return Success(); } S::Int S::GUI::WindowHaiku::Hide() { if (wnd == NIL) return Success(); if (!wnd->IsHidden()) { while (wnd->LockWithTimeout(0) != B_OK) Application::Lock::ResumeLock(Application::Lock::SuspendLock()); wnd->Hide(); wnd->Unlock(); } return Success(); } S::Int S::GUI::WindowHaiku::SetMetrics(const Point &nPos, const Size &nSize) { if (wnd == NIL) return Success(); /* If the window belongs to another thread, we * need to suspend our application lock in order * for the move and resize operations to finish. */ Int suspendCount = (wnd->Thread() != find_thread(NIL) ? Application::Lock::SuspendLock() : 0); /* Set window metrics. */ wnd->MoveTo(nPos.x, nPos.y); wnd->ResizeTo(Math::Round(nSize.cx * fontSize) + sizeModifier.cx - 1, Math::Round(nSize.cy * fontSize) + sizeModifier.cy - 1); /* Resume the application lock. */ Application::Lock::ResumeLock(suspendCount); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/windowbackend.cpp000077500000000000000000000066741516402577000266250ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2015 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::GUI::WindowBackend *CreateWindowBackend() { return new S::GUI::WindowBackend(); } S::GUI::WindowBackend *(*S::GUI::WindowBackend::backend_creator)() = &CreateWindowBackend; S::Int S::GUI::WindowBackend::SetBackend(WindowBackend *(*backend)()) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::GUI::WindowBackend *S::GUI::WindowBackend::CreateBackendInstance() { return backend_creator(); } S::GUI::WindowBackend::WindowBackend(Void *iWindow) { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) WindowGDI(); #endif type = WINDOW_NONE; drawSurface = NIL; doClose.Connect(True); } S::GUI::WindowBackend::~WindowBackend() { } S::Short S::GUI::WindowBackend::GetWindowType() const { return type; } S::Void *S::GUI::WindowBackend::GetSystemWindow() const { return NIL; } S::GUI::Surface *S::GUI::WindowBackend::GetDrawSurface() const { if (drawSurface != NIL) return drawSurface; else return Surface::GetNullSurface(); } S::Int S::GUI::WindowBackend::Open(const String &title, const Point &pos, const Size &size, Int flags) { return Success(); } S::Int S::GUI::WindowBackend::Close() { return Success(); } S::Int S::GUI::WindowBackend::RequestClose() { return Close(); } S::Int S::GUI::WindowBackend::SetTitle(const String &nTitle) { return Success(); } S::Int S::GUI::WindowBackend::SetIcon(const Bitmap &newIcon) { return Success(); } S::Int S::GUI::WindowBackend::SetIconDirect(Void *newIcon) { return Success(); } S::Int S::GUI::WindowBackend::EnableDropFiles(Bool nEnabled) { return Success(); } const S::Array &S::GUI::WindowBackend::GetDroppedFiles() const { static Array none; return none; } S::Int S::GUI::WindowBackend::SetMinimumSize(const Size &nMinSize) { return Success(); } S::Int S::GUI::WindowBackend::SetMaximumSize(const Size &nMaxSize) { return Success(); } S::Int S::GUI::WindowBackend::Show() { return Success(); } S::Int S::GUI::WindowBackend::Hide() { return Success(); } S::GUI::Rect S::GUI::WindowBackend::GetRestoredWindowRect() const { return Rect(); } S::Int S::GUI::WindowBackend::SetMetrics(const Point &nPos, const Size &nSize) { return Success(); } S::Int S::GUI::WindowBackend::Minimize() { return Success(); } S::Int S::GUI::WindowBackend::Maximize() { return Success(); } S::Int S::GUI::WindowBackend::Restore() { return Success(); } S::Int S::GUI::WindowBackend::Raise() { return Success(); } S::Int S::GUI::WindowBackend::SetProgressIndicator(Window::ProgressIndicatorState state, Float value) { return Success(); } const S::GUI::Size &S::GUI::WindowBackend::GetSizeModifier() const { return sizeModifier; } S::Void S::GUI::WindowBackend::SetSizeModifier(const Size &nSizeModifier) { sizeModifier = nSizeModifier; } const S::GUI::Rect &S::GUI::WindowBackend::GetUpdateRect() const { return updateRect; } smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/xlib/000077500000000000000000000000001516402577000242205ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/xlib/Makefile000066400000000000000000000011551516402577000256620ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags x11) endif endif endif # Enter object files here: OBJECTS = ifeq ($(BUILD_XLIB),True) OBJECTS += windowxlib.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/gui/window/backends/xlib/windowxlib.cpp000077500000000000000000001254621516402577000271270ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace X11; S::GUI::WindowBackend *CreateWindowXLib() { return new S::GUI::WindowXLib(); } S::Int windowXLibTmp = S::GUI::WindowBackend::SetBackend(&CreateWindowXLib); S::Int addWindowXLibInitTmp = S::AddInitFunction(&S::GUI::WindowXLib::Initialize); S::Int addWindowXLibFreeTmp = S::AddFreeFunction(&S::GUI::WindowXLib::Free); S::Array S::GUI::WindowXLib::windowBackends; S::GUI::Cursor *S::GUI::WindowXLib::activeCursor = NIL; S::GUI::Point S::GUI::WindowXLib::activeCursorPos; namespace smooth { namespace GUI { static int OnXIMPreeditStart(XIC ic, XPointer backend, XPointer dummy) { ((WindowXLib *) backend)->OnXIMPreeditStart(); return -1; } static void OnXIMPreeditDone(XIC ic, XPointer backend, XPointer dummy) { ((WindowXLib *) backend)->OnXIMPreeditDone(); } static void OnXIMPreeditDraw(XIC ic, XPointer backend, XIMPreeditDrawCallbackStruct *data) { ((WindowXLib *) backend)->OnXIMPreeditDraw(data); } static void OnXIMPreeditCaret(XIC ic, XPointer backend, XIMPreeditCaretCallbackStruct *data) { ((WindowXLib *) backend)->OnXIMPreeditCaret(data); } }; }; S::Int S::GUI::WindowXLib::Initialize() { /* Register for cursor events. */ Cursor::internalSetCursor.Connect(&WindowXLib::SetCursor); Cursor::internalRemoveCursor.Connect(&WindowXLib::RemoveCursor); return Success(); } S::Int S::GUI::WindowXLib::Free() { /* Unregister cursor event handlers. */ Cursor::internalSetCursor.Disconnect(&WindowXLib::SetCursor); Cursor::internalRemoveCursor.Disconnect(&WindowXLib::RemoveCursor); return Success(); } S::GUI::WindowXLib::WindowXLib(Void *iWindow) { type = WINDOW_XLIB; display = Backends::BackendXLib::GetDisplay(); im = Backends::BackendXLib::GetIM(); if (display == NIL) { fprintf(stderr, "Error: Unable to open display.\n"); exit(EXIT_FAILURE); } wnd = None; oldwnd = None; ic = NIL; iwnd = None; id = windowBackends.Add(this); minSize = Size(160, 24); maximized = False; fontSize = Surface().GetSurfaceDPI() / 96.0; flags = 0; sysIcon = NIL; sysIconSize = 0; xdndTimeStamp = CurrentTime; acceptDrop = False; enableDropFiles = False; } S::GUI::WindowXLib::~WindowXLib() { if (sysIcon != NIL) { delete [] sysIcon; sysIcon = NIL; sysIconSize = 0; } windowBackends.Remove(id); } S::Void S::GUI::WindowXLib::UpdateWMNormalHints() { if (wnd == None) return; XSizeHints normal; normal.flags = (minSize != Size() ? PMinSize : 0) | (maxSize != Size() ? PMaxSize : 0) | (flags & WF_NORESIZE ? PPosition | PSize : 0); normal.x = pos.x; normal.y = pos.y; normal.width = Math::Round(size.cx * fontSize) + sizeModifier.cx; normal.height = Math::Round(size.cy * fontSize) + sizeModifier.cy; normal.min_width = Math::Round(minSize.cx * fontSize) + sizeModifier.cx; normal.min_height = Math::Round(minSize.cy * fontSize) + sizeModifier.cy; normal.max_width = Math::Round(maxSize.cx * fontSize) + sizeModifier.cx; normal.max_height = Math::Round(maxSize.cy * fontSize) + sizeModifier.cy; XSetWMNormalHints(display, wnd, &normal); } S::Void *S::GUI::WindowXLib::GetSystemWindow() const { return (Void *) wnd; } S::GUI::WindowXLib *S::GUI::WindowXLib::GetWindowBackend(X11::Window wnd) { if (wnd == None) return NIL; foreach (WindowXLib *window, windowBackends) { if (window == NIL) continue; if (window->wnd == wnd || window->iwnd == wnd || window->oldwnd == wnd) return window; } return NIL; } S::Input::Keyboard::Key S::GUI::WindowXLib::ConvertKey(Int keySym) { Input::Keyboard::Key key = Input::Keyboard::KeyOther; switch (keySym) { case XK_Left: key = Input::Keyboard::KeyLeft; break; case XK_Up: key = Input::Keyboard::KeyUp; break; case XK_Right: key = Input::Keyboard::KeyRight; break; case XK_Down: key = Input::Keyboard::KeyDown; break; case XK_Home: key = Input::Keyboard::KeyHome; break; case XK_End: key = Input::Keyboard::KeyEnd; break; case XK_Insert: key = Input::Keyboard::KeyInsert; break; case XK_Delete: key = Input::Keyboard::KeyDelete; break; case XK_Prior: key = Input::Keyboard::KeyPrior; break; case XK_Next: key = Input::Keyboard::KeyNext; break; case XK_Return: key = Input::Keyboard::KeyReturn; break; case XK_BackSpace: key = Input::Keyboard::KeyBack; break; case XK_Tab: key = Input::Keyboard::KeyTab; break; case XK_space: key = Input::Keyboard::KeySpace; break; case XK_Shift_L: case XK_Shift_R: key = Input::Keyboard::KeyShift; break; case XK_Control_L: case XK_Control_R: key = Input::Keyboard::KeyControl; break; case XK_Alt_L: case XK_Alt_R: key = Input::Keyboard::KeyAlt; break; case XK_Escape: key = Input::Keyboard::KeyEscape; break; case XK_F1: key = Input::Keyboard::KeyF1; break; case XK_F2: key = Input::Keyboard::KeyF2; break; case XK_F3: key = Input::Keyboard::KeyF3; break; case XK_F4: key = Input::Keyboard::KeyF4; break; case XK_F5: key = Input::Keyboard::KeyF5; break; case XK_F6: key = Input::Keyboard::KeyF6; break; case XK_F7: key = Input::Keyboard::KeyF7; break; case XK_F8: key = Input::Keyboard::KeyF8; break; case XK_F9: key = Input::Keyboard::KeyF9; break; case XK_F10: key = Input::Keyboard::KeyF10; break; case XK_F11: key = Input::Keyboard::KeyF11; break; case XK_F12: key = Input::Keyboard::KeyF12; break; case XK_F13: key = Input::Keyboard::KeyF13; break; case XK_F14: key = Input::Keyboard::KeyF14; break; case XK_F15: key = Input::Keyboard::KeyF15; break; case XK_F16: key = Input::Keyboard::KeyF16; break; case XK_F17: key = Input::Keyboard::KeyF17; break; case XK_F18: key = Input::Keyboard::KeyF18; break; case XK_F19: key = Input::Keyboard::KeyF19; break; case XK_F20: key = Input::Keyboard::KeyF20; break; case XK_F21: key = Input::Keyboard::KeyF21; break; case XK_F22: key = Input::Keyboard::KeyF22; break; case XK_F23: key = Input::Keyboard::KeyF23; break; case XK_F24: key = Input::Keyboard::KeyF24; break; } if (keySym >= '0' && keySym <= '9') key = (Input::Keyboard::Key) keySym; else if (keySym >= 'A' && keySym <= 'Z') key = (Input::Keyboard::Key) keySym; else if (keySym >= 'a' && keySym <= 'z') key = (Input::Keyboard::Key) (keySym + ('A' - 'a')); return key; } S::Int S::GUI::WindowXLib::ProcessSystemMessages(XEvent *e) { static Int focusWndID = -1; static Atom mimeURIListAtom = XInternAtom(display, "text/uri-list", False); static Atom wmProtocolsAtom = XInternAtom(display, "WM_PROTOCOLS", False); static Atom wmDeleteWindowAtom = XInternAtom(display, "WM_DELETE_WINDOW", False); static Atom wmPingAtom = XInternAtom(display, "_NET_WM_PING", False); static Atom wmStateAtom = XInternAtom(display, "_NET_WM_STATE", False); static Atom wmStateMaximizedHorzAtom = XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); static Atom wmStateMaximizedVertAtom = XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_VERT", False); static Atom xaTargets = XInternAtom(display, "TARGETS", True); static Atom xaClipboard = XInternAtom(display, "CLIPBOARD", True); static Atom xaUtf8String = XInternAtom(display, "UTF8_STRING", True); static Atom xdndEnterAtom = XInternAtom(display, "XdndEnter", False); static Atom xdndTypeListAtom = XInternAtom(display, "XdndTypeList", False); static Atom xdndPositionAtom = XInternAtom(display, "XdndPosition", False); static Atom xdndStatusAtom = XInternAtom(display, "XdndStatus", False); static Atom xdndDropAtom = XInternAtom(display, "XdndDrop", False); static Atom xdndLeaveAtom = XInternAtom(display, "XdndLeave", False); static Atom xdndFinishedAtom = XInternAtom(display, "XdndFinished", False); static Atom xdndActionCopyAtom = XInternAtom(display, "XdndActionCopy", False); /* Lock application while processing messages. */ Application::Lock lock; /* Process system events not relevant * to portable Window implementation. */ switch (e->type) { case CreateNotify: onCreate.Emit(); break; case DestroyNotify: onDestroy.Emit(); oldwnd = None; break; case MapNotify: /* Set internal focus window. */ focusWndID = id; /* Grab focus unless we are a tool window. */ if (!(flags & WF_TOPMOST && flags & WF_NOTASKBUTTON && flags & WF_THINBORDER)) XSetInputFocus(display, wnd, RevertToParent, CurrentTime); /* Initialize window metrics here to handle X servers * that do not send a ConfigureNotify to new windows. */ if (wnd == e->xany.window) { XWindowAttributes attributes; XGetWindowAttributes(display, wnd, &attributes); /* Get screen coordinates for window. */ X11::Window child = 0; XTranslateCoordinates(display, wnd, RootWindow(display, DefaultScreen(display)), 0, 0, &attributes.x, &attributes.y, &child); /* Set metrics and emit window metrics event. */ pos = Point(attributes.x, attributes.y); size = (Size(attributes.width, attributes.height) - sizeModifier) / fontSize; if (drawSurface != NIL) drawSurface->SetSize(Size(attributes.width, attributes.height)); onEvent.Call(SM_WINDOWMETRICS, (( attributes.x + 32768) << 16) | ( attributes.y + 32768), ((Math::Round(attributes.width / fontSize) + 32768) << 16) | (Math::Round(attributes.height / fontSize) + 32768)); onEvent.Call(SM_GETFOCUS, 0, 0); } break; case UnmapNotify: /* Clear internal focus window. */ if (focusWndID == id) focusWndID = -1; break; case PropertyNotify: if (wnd == e->xany.window && e->xproperty.atom == wmStateAtom && e->xproperty.state == PropertyNewValue) { Bool maximizedNow = False; Int atomsRead = 0; unsigned long bytesRemaining = 4; while (bytesRemaining) { Atom actualType; int actualFormat; unsigned long actualItems; Atom *wmStateValueAtom; XGetWindowProperty(display, wnd, wmStateAtom, atomsRead++, 1, False, XA_ATOM, &actualType, &actualFormat, &actualItems, &bytesRemaining, (unsigned char **) &wmStateValueAtom); if (actualItems == 1) { if (*wmStateValueAtom == wmStateMaximizedHorzAtom || *wmStateValueAtom == wmStateMaximizedVertAtom) maximizedNow = True; XFree(wmStateValueAtom); } } if ( maximizedNow && !maximized) onMaximize.Emit(); else if (!maximizedNow && maximized) onRestore.Emit(); maximized = maximizedNow; } break; case SelectionRequest: { String text; if (e->xselectionrequest.selection == XA_PRIMARY) text = selection; else if (e->xselectionrequest.selection == xaClipboard) text = clipboard; if (text == NIL) break; XEvent respond; respond.xselection.type = SelectionNotify; respond.xselection.display = e->xselectionrequest.display; respond.xselection.requestor = e->xselectionrequest.requestor; respond.xselection.selection = e->xselectionrequest.selection; respond.xselection.target = e->xselectionrequest.target; respond.xselection.property = e->xselectionrequest.property; respond.xselection.time = e->xselectionrequest.time; if (e->xselectionrequest.target == xaTargets) { Atom targets[] = { XA_STRING, xaUtf8String }; XChangeProperty(display, e->xselectionrequest.requestor, e->xselectionrequest.property, XA_ATOM, 32, PropModeReplace, (unsigned char *) targets, 2); } else if (e->xselectionrequest.target == XA_STRING) { XChangeProperty(display, e->xselectionrequest.requestor, e->xselectionrequest.property, XA_STRING, 8, PropModeReplace, (unsigned char *) (char *) text, text.Length()); } else if (e->xselectionrequest.target == xaUtf8String) { XChangeProperty(display, e->xselectionrequest.requestor, e->xselectionrequest.property, xaUtf8String, 8, PropModeReplace, (unsigned char *) text.ConvertTo("UTF-8"), strlen(text.ConvertTo("UTF-8"))); } else { /* Strings only please! */ respond.xselection.property = None; } XSendEvent(display, e->xselectionrequest.requestor, 0, 0, &respond); XFlush(display); } break; case SelectionClear: if (e->xselectionclear.selection == XA_PRIMARY) selection = NIL; else if (e->xselectionclear.selection == xaClipboard) clipboard = NIL; break; } /* Check if window still matches the event. */ if (e->xany.window != wnd && e->xany.window != iwnd) return Error(); /* Convert Xlib events to smooth messages. */ switch (e->type) { /* Mouse events: */ case MotionNotify: /* Update pointer position in Input::Pointer. */ Input::Pointer::UpdatePosition(Window::GetWindow((Void *) e->xmotion.window), e->xmotion.x_root, e->xmotion.y_root); onEvent.Call(SM_MOUSEMOVE, 0, 0); break; case EnterNotify: /* Update pointer position in Input::Pointer. */ Input::Pointer::UpdatePosition(Window::GetWindow((Void *) e->xcrossing.window), e->xcrossing.x_root, e->xcrossing.y_root); onEvent.Call(SM_MOUSEMOVE, 0, 0); break; case LeaveNotify: /* Update pointer position in Input::Pointer. */ Input::Pointer::UpdatePosition(NIL, e->xcrossing.x_root, e->xcrossing.y_root); onEvent.Call(SM_MOUSEMOVE, 0, 0); break; case ButtonPress: /* Update pointer position in Input::Pointer. */ Input::Pointer::UpdatePosition(Window::GetWindow((Void *) e->xbutton.window), e->xbutton.x_root, e->xbutton.y_root); /* Reject if a modal window is active. */ if (IsModalWindowActive()) break; /* Handle focus if we are not a utility window. */ if (!(flags & WF_TOPMOST && flags & WF_NOTASKBUTTON && flags & WF_THINBORDER)) { X11::Window focusWnd = None; int revertTo = RevertToNone; XGetInputFocus(display, &focusWnd, &revertTo); /* Grab focus if an ancestor of ourselves is focussed. */ foreach (WindowXLib *backend, windowBackends) { if (backend == this) break; else if (backend->wnd != focusWnd) continue; XSetInputFocus(display, focusWnd = wnd, RevertToParent, CurrentTime); break; } /* Reject button messages if we do not have the focus at this point, * which usually means that some modal window is blocking. */ if (focusWnd == None || (focusWnd != wnd && focusWnd != iwnd)) break; } /* Pass message to smooth window. */ { static XButtonEvent prevButtonEvent; static Bool prevButtonEventInitialized = False; if (!prevButtonEventInitialized) { prevButtonEvent.button = 0; prevButtonEvent.time = 0; prevButtonEvent.x = 0; prevButtonEvent.y = 0; prevButtonEventInitialized = True; } if ((e->xbutton.button == Button1 || e->xbutton.button == Button2 || e->xbutton.button == Button3) && e->xbutton.button == prevButtonEvent.button && e->xbutton.time <= prevButtonEvent.time + 500 && Math::Abs(e->xbutton.x - prevButtonEvent.x) <= 5 && Math::Abs(e->xbutton.y - prevButtonEvent.y) <= 5) { if (e->xbutton.button == Button1) onEvent.Call(SM_LBUTTONDBLCLK, 0, 0); else if (e->xbutton.button == Button2) onEvent.Call(SM_MBUTTONDBLCLK, 0, 0); else if (e->xbutton.button == Button3) onEvent.Call(SM_RBUTTONDBLCLK, 0, 0); } else { if (e->xbutton.button == Button1) onEvent.Call(SM_LBUTTONDOWN, 0, 0); else if (e->xbutton.button == Button2) onEvent.Call(SM_MBUTTONDOWN, 0, 0); else if (e->xbutton.button == Button3) onEvent.Call(SM_RBUTTONDOWN, 0, 0); else if (e->xbutton.button == Button4) onEvent.Call(SM_MOUSEWHEEL, 120, 0); else if (e->xbutton.button == Button5) onEvent.Call(SM_MOUSEWHEEL, -120, 0); } prevButtonEvent = e->xbutton; } /* Grab the keyboard focus if we don't have it already. */ if (wnd != None && focusWndID != id && e->xbutton.button <= 3) { WindowXLib *focusWnd = windowBackends.Get(focusWndID); if (focusWnd != NIL) focusWnd->onEvent.Call(SM_LOSEFOCUS, Window::GetWindow((Void *) wnd)->GetHandle(), 0); focusWndID = id; onEvent.Call(SM_GETFOCUS, 0, 0); } break; case ButtonRelease: /* Update pointer position in Input::Pointer. */ Input::Pointer::UpdatePosition(Window::GetWindow((Void *) e->xbutton.window), e->xbutton.x_root, e->xbutton.y_root); /* Pass message to smooth window. */ if (e->xbutton.button == Button1) onEvent.Call(SM_LBUTTONUP, 0, 0); else if (e->xbutton.button == Button2) onEvent.Call(SM_MBUTTONUP, 0, 0); else if (e->xbutton.button == Button3) onEvent.Call(SM_RBUTTONUP, 0, 0); break; /* Keyboard events: */ case KeymapNotify: XRefreshKeyboardMapping(&e->xmapping); break; case KeyPress: Input::Keyboard::UpdateKeyState(ConvertKey(XkbKeycodeToKeysym(display, e->xkey.keycode, 0, 0)), True); onEvent.Call(SM_KEYDOWN, ConvertKey(XkbKeycodeToKeysym(display, e->xkey.keycode, 0, 0)), 0); /* Convert keyboard event to input string and * call SM_CHAR event for each character. */ if (ic != NIL) { Status status; char text[32]; Int numChars = Xutf8LookupString(ic, &e->xkey, text, 32, NIL, &status); text[numChars] = 0; if (status == XLookupChars) { String string; string.ImportFrom("UTF-8", text); for (Int i = 0; i < string.Length(); i++) onEvent.Call(SM_CHAR, string[i], 0); } } else { char text[32]; Int numChars = XLookupString(&e->xkey, text, 32, NIL, NIL); for (Int i = 0; i < numChars; i++) onEvent.Call(SM_CHAR, text[i], 0); } break; case KeyRelease: Input::Keyboard::UpdateKeyState(ConvertKey(XkbKeycodeToKeysym(display, e->xkey.keycode, 0, 0)), False); onEvent.Call(SM_KEYUP, ConvertKey(XkbKeycodeToKeysym(display, e->xkey.keycode, 0, 0)), 0); break; /* Paint events: */ case Expose: /* Fill update rect. */ if (updateRect == Rect()) { updateRect.left = e->xexpose.x; updateRect.top = e->xexpose.y; updateRect.right = e->xexpose.x + e->xexpose.width; updateRect.bottom = e->xexpose.y + e->xexpose.height; } else { updateRect.left = Math::Min(updateRect.left, e->xexpose.x); updateRect.top = Math::Min(updateRect.top, e->xexpose.y); updateRect.right = Math::Max(updateRect.right, e->xexpose.x + e->xexpose.width); updateRect.bottom = Math::Max(updateRect.bottom, e->xexpose.y + e->xexpose.height); } /* Emit paint event if this was the * last queued expose notification. */ if (e->xexpose.count == 0) { onEvent.Call(SM_PAINT, 0, 0); updateRect = Rect(); } break; /* Window state change events: */ case ConfigureNotify: /* Process window metrics changes. */ { static Size prevSize; /* Get screen coordinates for window. */ if (wnd != None && !e->xconfigure.send_event) { X11::Window child = 0; XTranslateCoordinates(display, wnd, RootWindow(display, DefaultScreen(display)), 0, 0, &e->xconfigure.x, &e->xconfigure.y, &child); } /* Set metrics and emit window metrics event. */ pos = Point(e->xconfigure.x, e->xconfigure.y); size = (Size(e->xconfigure.width, e->xconfigure.height) - sizeModifier) / fontSize; if (drawSurface != NIL) drawSurface->SetSize(Size(e->xconfigure.width, e->xconfigure.height)); onEvent.Call(SM_WINDOWMETRICS, (( e->xconfigure.x + 32768) << 16) | ( e->xconfigure.y + 32768), ((Math::Round(e->xconfigure.width / fontSize) + 32768) << 16) | (Math::Round(e->xconfigure.height / fontSize) + 32768)); /* Update window rect and emit paint event if necessary. */ if (size != prevSize) { if (!maximized) restoredRect = Rect(pos, size); updateRect.left = Math::Min(updateRect.left, 0); updateRect.top = Math::Min(updateRect.top, 0); updateRect.right = Math::Max(updateRect.right, e->xconfigure.width); updateRect.bottom = Math::Max(updateRect.bottom, e->xconfigure.height); onEvent.Call(SM_PAINT, 0, 0); updateRect = Rect(); } prevSize = size; } break; case FocusIn: focusWndID = id; onEvent.Call(SM_GETFOCUS, 0, 0); break; case FocusOut: Input::Keyboard::ResetKeyState(); /* Get the window that now has the focus. */ { X11::Window focusWnd = None; int revertTo = RevertToNone; XGetInputFocus(display, &focusWnd, &revertTo); if (focusWnd != iwnd) { Window *window = Window::GetWindow((Void *) focusWnd); onEvent.Call(SM_LOSEFOCUS, window != NIL ? window->GetHandle() : -1, 0); } } break; /* Client message events: */ case ClientMessage: /* Handle window manager request. */ if (e->xclient.message_type == wmProtocolsAtom) { if ((Atom) e->xclient.data.l[0] == wmDeleteWindowAtom) { if (doClose.Call()) Close(); } else if ((Atom) e->xclient.data.l[0] == wmPingAtom) { e->xclient.window = RootWindow(display, DefaultScreen(display)); XSendEvent(display, e->xclient.window, 0, SubstructureNotifyMask | SubstructureRedirectMask, e); XFlush(display); } } /* Handle XdndEnter message. */ if (e->xclient.message_type == xdndEnterAtom) { /* Check if the dropped item is a file. */ X11::Window sourceWnd = e->xclient.data.l[0]; if (e->xclient.data.l[1] & 1) { Int typesRead = 0; unsigned long bytesRemaining = 4; while (bytesRemaining) { Atom actualType; int actualFormat; unsigned long actualItems; Atom *xdndType; XGetWindowProperty(display, sourceWnd, xdndTypeListAtom, typesRead++, 1, False, XA_ATOM, &actualType, &actualFormat, &actualItems, &bytesRemaining, (unsigned char **) &xdndType); if (*xdndType == mimeURIListAtom) acceptDrop = True; XFree(xdndType); } } else if ((Atom) e->xclient.data.l[2] == mimeURIListAtom || (Atom) e->xclient.data.l[3] == mimeURIListAtom || (Atom) e->xclient.data.l[4] == mimeURIListAtom) { acceptDrop = True; } } /* Handle XdndPosition message. */ if (e->xclient.message_type == xdndPositionAtom) { Window *window = Window::GetWindow((Void *) wnd); Input::Pointer::UpdatePosition(window, e->xclient.data.l[2] >> 16, e->xclient.data.l[2] & 0xFFFF); /* Send XdndStatus message. */ XEvent status; X11::Window sourceWnd = e->xclient.data.l[0]; status.xclient.type = ClientMessage; status.xclient.display = display; status.xclient.window = sourceWnd; status.xclient.message_type = xdndStatusAtom; status.xclient.format = 32; status.xclient.data.l[0] = wnd; status.xclient.data.l[1] = acceptDrop; status.xclient.data.l[2] = (pos.x << 16) | pos.y; status.xclient.data.l[3] = (size.cx << 16) | size.cy; status.xclient.data.l[4] = xdndActionCopyAtom; XSendEvent(display, sourceWnd, 0, 0, &status); XFlush(display); } /* Handle XdndDrop message. */ if (e->xclient.message_type == xdndDropAtom) { /* Are we interested at all? */ if (acceptDrop) { Point position = Window::GetWindow((Void *) wnd)->GetMousePosition(); xdndTimeStamp = e->xclient.data.l[2]; onEvent.Call(SM_DROPFILES, position.x, position.y); } /* Send XdndFinished message. */ XEvent finished; X11::Window sourceWnd = e->xclient.data.l[0]; finished.xclient.type = ClientMessage; finished.xclient.display = display; finished.xclient.window = sourceWnd; finished.xclient.message_type = xdndFinishedAtom; finished.xclient.format = 32; finished.xclient.data.l[0] = wnd; finished.xclient.data.l[1] = acceptDrop; finished.xclient.data.l[2] = xdndActionCopyAtom; XSendEvent(display, sourceWnd, 0, 0, &finished); XFlush(display); } /* Clean up after XdndDrop or on XdndLeave message. */ if (e->xclient.message_type == xdndDropAtom || e->xclient.message_type == xdndLeaveAtom) { xdndTimeStamp = CurrentTime; acceptDrop = False; } break; } return Success(); } S::Int S::GUI::WindowXLib::Open(const String &title, const Point &pos, const Size &size, Int iFlags) { static Atom wmDeleteWindowAtom = XInternAtom(display, "WM_DELETE_WINDOW", False); static Atom wmPingAtom = XInternAtom(display, "_NET_WM_PING", False); static Atom wmIconAtom = XInternAtom(display, "_NET_WM_ICON", False); static Atom windowStateAtom = XInternAtom(display, "_NET_WM_STATE", False); static Atom windowStateAboveAtom = XInternAtom(display, "_NET_WM_STATE_ABOVE", False); static Atom windowStateModalAtom = XInternAtom(display, "_NET_WM_STATE_MODAL", False); static Atom windowTypeAtom = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); static Atom windowTypeNormalAtom = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False); static Atom windowTypeDialogAtom = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False); static Atom windowTypeUtilityAtom = XInternAtom(display, "_NET_WM_WINDOW_TYPE_UTILITY", False); flags = iFlags; restoredRect = Rect(pos, size); XSetWindowAttributes attributes; attributes.background_pixel = Setup::BackgroundColor; attributes.bit_gravity = NorthWestGravity; attributes.save_under = False; attributes.override_redirect = False; if (flags & WF_NOTITLE ) attributes.override_redirect = True; if (flags & WF_TOPMOST && flags & WF_NOTASKBUTTON && flags & WF_THINBORDER ) attributes.save_under = True; wnd = XCreateWindow(display, RootWindow(display, 0), pos.x, pos.y, Math::Round(size.cx * fontSize) + sizeModifier.cx, Math::Round(size.cy * fontSize) + sizeModifier.cy, 0, CopyFromParent, InputOutput, CopyFromParent, CWBackPixel | CWBitGravity | CWSaveUnder | CWOverrideRedirect, &attributes); if (wnd != None) { /* Create input window. */ if (im != NIL) { XLockDisplay(display); iwnd = XCreateWindow(display, wnd, 0, 0, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, 0, NIL); XMapWindow(display, iwnd); XUnlockDisplay(display); } /* Select event types we want to receive. */ XSelectInput(display, wnd, ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | StructureNotifyMask | PropertyChangeMask); /* Opt in to the WM_DELETE_WINDOW and _NET_WM_PING protocols. */ Atom protocols[2] = { wmDeleteWindowAtom, wmPingAtom }; XSetWMProtocols(display, wnd, protocols, 2); /* Process the CreateNotify event again, as GetWindowBackend * cannot find the correct backend until wnd is set. */ XEvent e; e.type = CreateNotify; ProcessSystemMessages(&e); /* Create drawing surface. */ if ((flags & WF_THINBORDER) || (flags & WF_NORESIZE)) drawSurface = new Surface((Void *) wnd, size * fontSize + sizeModifier); else drawSurface = new Surface((Void *) wnd); drawSurface->SetSize(size * fontSize + sizeModifier); /* Set application name. */ for (Int i = 0; i < Object::GetNOfObjects(); i++) { if (Object::GetNthObject(i)->GetObjectType() != Application::classID) continue; Application *application = (Application *) Object::GetNthObject(i); XClassHint *classHint = XAllocClassHint(); classHint->res_name = application->GetText(); classHint->res_class = application->GetText(); XSetClassHint(display, wnd, classHint); XFree(classHint); break; } /* Set window title. */ SetTitle(title); /* Set icon. */ if (sysIcon != NIL) { XChangeProperty(display, wnd, wmIconAtom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) sysIcon, sysIconSize); } /* Set minimum and maximum size. */ if (flags & WF_NORESIZE) { minSize = size; maxSize = size; } UpdateWMNormalHints(); /* Configure window type. */ if ((flags & WF_TOPMOST) && (flags & WF_NOTASKBUTTON) && (flags & WF_THINBORDER)) { XChangeProperty(display, wnd, windowTypeAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) &windowTypeUtilityAtom, 1); } else if (flags & WF_TOPMOST) { XChangeProperty(display, wnd, windowTypeAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) &windowTypeDialogAtom, 1); XChangeProperty(display, wnd, windowStateAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) &windowStateAboveAtom, 1); } else if (flags & WF_MODAL) { XChangeProperty(display, wnd, windowTypeAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) &windowTypeDialogAtom, 1); XChangeProperty(display, wnd, windowStateAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) &windowStateModalAtom, 1); } else { XChangeProperty(display, wnd, windowTypeAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) &windowTypeNormalAtom, 1); } /* Set transient hint. */ Widget *container = Window::GetWindow((Void *) wnd)->GetContainer(); if (container != NIL) { Window *parent = container->GetContainerWindow(); WindowXLib *leader = FindLeaderWindow(); if (parent != NIL) XSetTransientForHint(display, wnd, (X11::Window) parent->GetSystemWindow()); else if (leader != NIL) XSetTransientForHint(display, wnd, leader->wnd); } /* Enable dropping files if requested. */ if (enableDropFiles) EnableDropFiles(True); return Success(); } return Error(); } S::Int S::GUI::WindowXLib::Close() { if (wnd == None) return Success(); /* Delete surface. */ if (drawSurface != NIL) delete drawSurface; drawSurface = NIL; /* Destroy input context. */ DestroyInputContext(); /* Destroy input window. */ if (iwnd != None) { XDestroyWindow(display, iwnd); iwnd = None; } /* Destroy window. */ XDestroyWindow(display, wnd); oldwnd = wnd; wnd = None; return Success(); } S::Int S::GUI::WindowXLib::RequestClose() { if (doClose.Call()) return Close(); return Success(); } S::GUI::WindowXLib *S::GUI::WindowXLib::FindLeaderWindow() { /* The leader window is the newest non topmost window. */ foreachreverse (WindowXLib *backend, windowBackends) { if ( backend->id < id && backend->wnd != None && !(backend->flags & WF_TOPMOST)) return backend; } return NIL; } S::Bool S::GUI::WindowXLib::IsModalWindowActive() { /* Ignore modal windows if this is a topmost window. */ if (flags & WF_TOPMOST) return False; /* Look for modal windows opened after ourselves. */ foreachreverse (WindowXLib *backend, windowBackends) { if (backend == this) return False; else if (backend->wnd != None && backend->flags & WF_MODAL) return True; } return False; } S::Int S::GUI::WindowXLib::SetTitle(const String &nTitle) { if (wnd == None) return Error(); static Atom wmNameAtom = XInternAtom(display, "_NET_WM_NAME", False); static Atom wmIconNameAtom = XInternAtom(display, "_NET_WM_ICON_NAME", False); XTextProperty titleProp; XTextProperty titlePropUTF8; const char *title = nTitle.ConvertTo("ISO-8859-1"); const char *titleUTF8 = nTitle.ConvertTo("UTF-8"); /* Set ISO encoded window name. */ if (XStringListToTextProperty((char **) &title, 1, &titleProp) != 0) { XSetWMName(display, wnd, &titleProp); XSetWMIconName(display, wnd, &titleProp); XFree(titleProp.value); } /* Set UTF-8 encoded window name. */ if (Xutf8TextListToTextProperty(display, (char **) &titleUTF8, 1, XUTF8StringStyle, &titlePropUTF8) == 0) { XSetTextProperty(display, wnd, &titlePropUTF8, wmNameAtom); XSetTextProperty(display, wnd, &titlePropUTF8, wmIconNameAtom); XFree(titlePropUTF8.value); } return Success(); } S::Int S::GUI::WindowXLib::SetIcon(const Bitmap &newIcon) { if (sysIcon != NIL) { delete [] sysIcon; sysIcon = NIL; sysIconSize = 0; } Int index = 0; Size size = newIcon.GetSize(); Int depth = newIcon.GetDepth(); sysIconSize = 2 + size.cx * size.cy; sysIcon = new UnsignedLong [sysIconSize]; sysIcon[index++] = size.cx; sysIcon[index++] = size.cy; Color backgroundColor16 = ((Setup::BackgroundColor.GetBlue() >> 3) << 11) | ((Setup::BackgroundColor.GetGreen() >> 2) << 5) | (Setup::BackgroundColor.GetRed() >> 3); Color backgroundColor24 = Setup::BackgroundColor; XImage *image = (XImage *) newIcon.GetSystemBitmap(); for (Int y = 0; y < size.cy; y++) { for (Int x = 0; x < size.cx; x++) { Long value = XGetPixel(image, x, y); if (depth == 16) sysIcon[index++] = (value == backgroundColor16 ? 0 : 255) << 24 | (((value >> 11) & 0x1F) << 19) | (((value >> 5) & 0x3F) << 10) | ((value & 0x1F) << 3); else if (depth == 24) sysIcon[index++] = (value == backgroundColor24 ? 0 : 255) << 24 | value; else if (depth == 32) sysIcon[index++] = value; } } return Success(); } S::Int S::GUI::WindowXLib::EnableDropFiles(Bool nEnableDropFiles) { enableDropFiles = nEnableDropFiles; if (wnd == None) return Success(); static Atom xdndAwareAtom = XInternAtom(display, "XdndAware", False); Int32 xdndVersion = 5; if (enableDropFiles) XChangeProperty(display, wnd, xdndAwareAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) &xdndVersion, 1); else XDeleteProperty(display, wnd, xdndAwareAtom); return Success(); } const S::Array &S::GUI::WindowXLib::GetDroppedFiles() const { static Atom mimeURIListAtom = XInternAtom(display, "text/uri-list", False); static Atom xdndSelectionAtom = XInternAtom(display, "XdndSelection", False); static Array fileNames; fileNames.RemoveAll(); XConvertSelection(display, xdndSelectionAtom, mimeURIListAtom, XA_PRIMARY, wnd, xdndTimeStamp); XFlush(display); /* Wait for SelectionNotify event to be sent. */ XEvent event; do { XNextEvent(display, &event); WindowXLib *backend = GUI::WindowXLib::GetWindowBackend(event.xany.window); if (backend != NIL) backend->ProcessSystemMessages(&event); } while (event.type != SelectionNotify); Atom type; int format; unsigned long items, bytes; unsigned char *data = NIL; /* Do not get any data yet, see how much data is there. */ if (XGetWindowProperty(display, wnd, XA_PRIMARY, 0, 0, 0, AnyPropertyType, &type, &format, &items, &bytes, &data) == 0) { if (data != NIL) { XFree(data); data = NIL; } /* Data is there! */ if (bytes > 0) XGetWindowProperty(display, wnd, XA_PRIMARY, 0, bytes, 0, AnyPropertyType, &type, &format, &items, &bytes, &data); } if (data == NIL) return fileNames; /* Query data. */ IO::InStream in(IO::STREAM_BUFFER, data, strlen((char *) data) + 1); while (in.GetPos() < in.Size()) { String line = in.InputLine(); if (line.StartsWith("#")) continue; if (line.StartsWith("file://")) { String host = line.SubString(7, line.Tail(line.Length() - 7).Find("/")); fileNames.Add(Encoding::URLEncode::Decode(line.Tail(line.Length() - 7 - host.Length()))); } } in.Close(); XFree(data); return fileNames; } S::Int S::GUI::WindowXLib::SetMinimumSize(const Size &nMinSize) { minSize = nMinSize; UpdateWMNormalHints(); if (wnd != None) { XResizeWindow(display, wnd, Math::Round(Math::Max(size.cx, minSize.cx) * fontSize) + sizeModifier.cx, Math::Round(Math::Max(size.cy, minSize.cy) * fontSize) + sizeModifier.cy); XFlush(display); } return Success(); } S::Int S::GUI::WindowXLib::SetMaximumSize(const Size &nMaxSize) { maxSize = nMaxSize; UpdateWMNormalHints(); if (wnd != None) { XResizeWindow(display, wnd, Math::Round(Math::Min(size.cx, maxSize.cx) * fontSize) + sizeModifier.cx, Math::Round(Math::Min(size.cy, maxSize.cy) * fontSize) + sizeModifier.cy); XFlush(display); } return Success(); } S::Int S::GUI::WindowXLib::Show() { if (wnd == None) return Success(); XMapRaised(display, wnd); XFlush(display); return Success(); } S::Int S::GUI::WindowXLib::Hide() { if (wnd == None) return Success(); XUnmapWindow(display, wnd); XFlush(display); return Success(); } S::Int S::GUI::WindowXLib::SetMetrics(const Point &nPos, const Size &nSize) { if (wnd == None) return Success(); XMoveResizeWindow(display, wnd, nPos.x, nPos.y, Math::Round(nSize.cx * fontSize) + sizeModifier.cx, Math::Round(nSize.cy * fontSize) + sizeModifier.cy); XFlush(display); return Success(); } S::Int S::GUI::WindowXLib::Maximize() { if (wnd == None) return Success(); static Atom wmStateAtom = XInternAtom(display, "_NET_WM_STATE", False); static Atom wmStateMaximizedHorzAtom = XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); static Atom wmStateMaximizedVertAtom = XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_VERT", False); static Atom wmStateMaximizedAtoms[2] = { wmStateMaximizedHorzAtom, wmStateMaximizedVertAtom }; if (!maximized) { XChangeProperty(display, wnd, wmStateAtom, XA_ATOM, 32, PropModeAppend, (unsigned char *) wmStateMaximizedAtoms, 2); XFlush(display); } return Success(); } S::Int S::GUI::WindowXLib::Raise() { if (wnd == None) return Success(); /* FixMe: Are there cases where we need to do anything here? */ XFlush(display); return Success(); } S::Void S::GUI::WindowXLib::OnXIMPreeditStart() { } S::Void S::GUI::WindowXLib::OnXIMPreeditDone() { } S::Void S::GUI::WindowXLib::OnXIMPreeditDraw(XIMPreeditDrawCallbackStruct *data) { if (activeCursor == NIL) return; /* Get preedit string if any. */ String string; if (data->text != NIL) { if (data->text->encoding_is_wchar) string = data->text->string.wide_char; else string.ImportFrom("UTF-8", data->text->string.multi_byte); } /* Draw string at cursor position. */ Rect rect = Rect::OverlapRect(Rect(activeCursorPos - Point(1, 1), activeCursor->GetRealSize()), Rect(activeCursor->GetRealPosition(), activeCursor->GetRealSize())); activeCursor->SetIMECursor(True); drawSurface->StartPaint(rect); drawSurface->Box(rect, activeCursor->GetBackgroundColor(), Rect::Filled); if (data->text != NIL) { for (Int i = 0; i < data->text->length; i++) { Font font = activeCursor->GetFont(); if (data->text->feedback != NIL) { if (data->text->feedback[i] & XIMUnderline) font.SetStyle(Font::Underline); } drawSurface->SetText(string.SubString(i, 1), rect + Point(font.GetScaledTextSizeX(string.Head(i)), 0), font); } } drawSurface->EndPaint(); activeCursor->SetIMEAdvance(activeCursor->GetFont().GetScaledTextSizeX(string.Head(data->caret))); activeCursor->SetIMECursor(False); } S::Void S::GUI::WindowXLib::OnXIMPreeditCaret(XIMPreeditCaretCallbackStruct *data) { } S::Void S::GUI::WindowXLib::CreateInputContext() { if (im == NIL) return; XLockDisplay(display); /* Set up callbacks. */ XIMCallback cbPeStart = { (XPointer) this, (XIMProc) S::GUI::OnXIMPreeditStart }; XIMCallback cbPeDone = { (XPointer) this, (XIMProc) S::GUI::OnXIMPreeditDone }; XIMCallback cbPeDraw = { (XPointer) this, (XIMProc) S::GUI::OnXIMPreeditDraw }; XIMCallback cbPeCaret = { (XPointer) this, (XIMProc) S::GUI::OnXIMPreeditCaret }; XVaNestedList preeditCbs = XVaCreateNestedList(0, XNPreeditStartCallback, &cbPeStart, XNPreeditDoneCallback, &cbPeDone, XNPreeditDrawCallback, &cbPeDraw, XNPreeditCaretCallback, &cbPeCaret, NULL); /* Create input context. */ ic = XCreateIC(im, XNClientWindow, wnd, XNInputStyle, XIMPreeditCallbacks | XIMStatusNothing, XNPreeditAttributes, preeditCbs, NULL); XFree(preeditCbs); if (ic == NIL) { /* Creating an IC for pre-editing can fail if the desktop environment does * not support it. Try creating one without pre-editing in that case. */ ic = XCreateIC(im, XNClientWindow, wnd, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL); } /* Configure input context. */ if (ic != NIL) { /* Set focus window. */ XSetICValues(ic, XNFocusWindow, iwnd, NULL); /* Get mask of filter events for IC. */ long filterEvents = 0; XGetICValues(ic, XNFilterEvents, &filterEvents, NULL); XSelectInput(display, iwnd, filterEvents); } XUnlockDisplay(display); } S::Void S::GUI::WindowXLib::DestroyInputContext() { if (ic == NIL) return; XLockDisplay(display); /* Reset event mask. */ XSelectInput(display, iwnd, 0); /* Clear input context. */ char *string = Xutf8ResetIC(ic); if (string != NIL) XFree(string); /* Destroy input context. */ XDestroyIC(ic); ic = NIL; XUnlockDisplay(display); } S::Void S::GUI::WindowXLib::SetCursor(Cursor *cursor, const Point &point) { WindowXLib *window = GetWindowBackend((X11::Window) cursor->GetContainerWindow()->GetSystemWindow()); if (window != NIL) { /* Remove active cursor. */ if (cursor != activeCursor && activeCursor != NIL) RemoveCursor(activeCursor); /* Create input context. */ window->CreateInputContext(); if (window->ic != NIL) { /* Move input window to cursor position. */ XMoveWindow(window->display, window->iwnd, point.x - 3, point.y + cursor->GetFont().GetScaledTextSizeY() + 1); /* Set input focus on input window. */ X11::Window focusWnd = None; int revertTo = RevertToNone; XGetInputFocus(window->display, &focusWnd, &revertTo); if (focusWnd != window->iwnd) { XSetInputFocus(window->display, window->iwnd, RevertToParent, CurrentTime); XFlush(window->display); } /* Set current input context. */ XSetICFocus(window->ic); } } activeCursor = cursor; activeCursorPos = point; } S::Void S::GUI::WindowXLib::RemoveCursor(Cursor *cursor) { if (activeCursor != cursor) return; WindowXLib *window = GetWindowBackend((X11::Window) cursor->GetContainerWindow()->GetSystemWindow()); if (window != NIL && window->ic != NIL) { /* Destroy input context. */ window->DestroyInputContext(); /* Clear preediting area. */ if (activeCursor->IsVisible()) { Rect rect = Rect::OverlapRect(Rect(activeCursorPos - Point(1, 1), activeCursor->GetRealSize()), Rect(activeCursor->GetRealPosition(), activeCursor->GetRealSize())); activeCursor->SetIMECursor(True); window->drawSurface->StartPaint(rect); window->drawSurface->Box(rect, activeCursor->GetBackgroundColor(), Rect::Filled); activeCursor->Paint(SP_PAINT); window->drawSurface->EndPaint(); activeCursor->SetIMECursor(False); } } activeCursor = NIL; activeCursorPos = Point(); } smooth-0.9.11~git20260403.0230c0da/classes/gui/window/toolwindow.cpp000077500000000000000000000045171516402577000244330ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include const S::Short S::GUI::ToolWindow::classID = S::Object::RequestClassID(); S::GUI::ToolWindow::ToolWindow(const Point &iPos, const Size &iSize) : Window("smooth ToolWindow", iPos, iSize) { type = classID; orientation = OR_FREE; visible = True; frameWidth = 0; backend->SetSizeModifier(Size()); SetFlags(WF_TOPMOST | WF_NOTASKBUTTON | WF_THINBORDER); } S::GUI::ToolWindow::~ToolWindow() { } S::Bool S::GUI::ToolWindow::Create() { if (IsRegistered()) { Window *containerWindow = container->GetContainerWindow(); if (containerWindow != NIL) { if (IsRightToLeft()) Window::SetMetrics(Point(containerWindow->GetRealSize().cx - (GetX() + GetRealSize().cx), GetY()), GetSize()); Window::SetMetrics(GetPosition() + containerWindow->GetPosition(), GetSize()); } } return Window::Create(); } S::Int S::GUI::ToolWindow::SetMetrics(const Point &nPos, const Size &nSize) { Point position = nPos; if (IsRegistered() && created) { Window *containerWindow = container->GetContainerWindow(); if (containerWindow != NIL) { if (IsRightToLeft()) { Surface *surface = GetDrawSurface(); Float fontSize = surface->GetSurfaceDPI() / 96.0; position.x = containerWindow->GetRealSize().cx - (nPos.x + Math::Round(nSize.cx * fontSize)); } position += containerWindow->GetPosition(); } } return Window::SetMetrics(position, nSize); } S::Bool S::GUI::ToolWindow::IsRightToLeft() const { if (IsRegistered() && layoutDirection == LD_DEFAULT) { Window *containerWindow = container->GetContainerWindow(); if (containerWindow != NIL) return containerWindow->IsRightToLeft(); } return Window::IsRightToLeft(); } S::Bool S::GUI::ToolWindow::IsTypeCompatible(Short compType) const { if (compType == Window::classID) return True; else return Window::IsTypeCompatible(compType); } smooth-0.9.11~git20260403.0230c0da/classes/gui/window/window.cpp000077500000000000000000000525641516402577000235420ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __WIN32__ # include # undef GetObject # if !defined SM_CXPADDEDBORDER # define SM_CXPADDEDBORDER 92 # endif #endif S::Array S::GUI::Window::windows; const S::Short S::GUI::Window::classID = S::Object::RequestClassID(); S::Short S::GUI::Window::nOfActiveWindows = 0; S::GUI::Window::Window(const String &title, const Point &iPos, const Size &iSize, Void *iWindow) : Widget(iPos, iSize) { backend = WindowBackend::CreateBackendInstance(); backend->onEvent.SetParentObject(this); backend->onEvent.Connect(&Window::Process, this); backend->onCreate.Connect(&Window::OnCreate, this); backend->onDestroy.Connect(&Window::OnDestroy, this); backend->onMinimize.Connect(&Window::OnMinimize, this); backend->onMaximize.Connect(&Window::OnMaximize, this); backend->onRestore.Connect(&Window::OnRestore, this); backend->doClose.Connect(&doClose); windows.Add(this, GetHandle()); maximized = False; minimized = False; type = classID; order = 0; layoutDirection = LD_DEFAULT; if (title != NIL) text = title; else text = "smooth Application"; #ifdef __WIN32__ frameWidth = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER); #else frameWidth = 1; backend->SetSizeModifier(Size(-6, -6)); #endif updateRect = Rect(Point(-1, -1), Size(0, 0)); icon = NIL; created = False; visible = False; destroyed = False; visibilitySet = False; mainLayer = new Layer(); Add(mainLayer); doClose.Connect(True); onCreate.SetParentObject(this); onPaint.SetParentObject(this); onEvent.SetParentObject(this); handleSystemMessage.Connect(MessageUnknown); } S::GUI::Window::~Window() { backend->onEvent.Disconnect(&Window::Process, this); if (created && !destroyed) backend->Close(); Remove(mainLayer); DeleteObject(mainLayer); windows.Remove(GetHandle()); delete backend; } S::Int S::GUI::Window::SetMetrics(const Point &nPos, const Size &nSize) { if (created && visible) backend->SetMetrics(nPos, nSize); Bool resized = (GetSize() != nSize); Bool prevVisible = visible; visible = False; Widget::SetMetrics(nPos, nSize); if (resized) CalculateOffsets(); visible = prevVisible; return Success(); } S::Int S::GUI::Window::SetIcon(const Bitmap &nIcon) { Bitmap newIcon = nIcon; #ifdef __WIN32__ if (newIcon == NIL) newIcon = ImageLoader::Load(String("Icon:").Append(String::FromInt(IDI_ICON))); #endif if (newIcon != NIL) { icon = newIcon; backend->SetIcon(icon); } return Success(); } S::Int S::GUI::Window::SetIconDirect(Void *nIcon) { backend->SetIconDirect(nIcon); return Success(); } S::Int S::GUI::Window::SetText(const String &nTitle) { text = nTitle; if (created && !destroyed) { Process(SM_WINDOWTITLECHANGED, 0, 0); backend->SetTitle(text); } return Success(); } S::Int S::GUI::Window::SetStatusText(const String &nStatus) { for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); if (widget == NIL) continue; if (widget->GetObjectType() == Statusbar::classID) { widget->SetText(nStatus); return Success(); } } return Error(); } const S::String &S::GUI::Window::GetStatusText() const { for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); if (widget == NIL) continue; if (widget->GetObjectType() == Statusbar::classID) return widget->GetText(); } return defaultStatus; } S::Int S::GUI::Window::SetDefaultStatusText(const String &nStatus) { defaultStatus = nStatus; RestoreDefaultStatusText(); return Success(); } S::Int S::GUI::Window::RestoreDefaultStatusText() { for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); if (widget == NIL) continue; if (widget->GetObjectType() == Statusbar::classID) { widget->SetText(defaultStatus); break; } } return Success(); } S::Int S::GUI::Window::SetProgressIndicator(ProgressIndicatorState state, Float value) { return backend->SetProgressIndicator(state, value); } const S::Array &S::GUI::Window::GetDroppedFiles() const { return backend->GetDroppedFiles(); } S::Int S::GUI::Window::SetRightToLeft(Bool nRightToLeft) { Surface *surface = GetDrawSurface(); surface->SetRightToLeft(nRightToLeft); layoutDirection = (nRightToLeft ? LD_RIGHTTOLEFT : LD_LEFTTORIGHT); return Success(); } S::Bool S::GUI::Window::IsRightToLeft() const { return ((layoutDirection == LD_DEFAULT) ? Setup::rightToLeft : (layoutDirection == LD_RIGHTTOLEFT)); } S::Int S::GUI::Window::Show() { order = Object::RequestObjectHandle(); if (!created) Create(); backend->SetMetrics(GetPosition(), GetSize()); onChangePosition.Emit(GetPosition()); onChangeSize.Emit(GetSize()); if (maximized && !visibilitySet) { backend->Hide(); maximized = False; Maximize(); } if (minimized && !visibilitySet) { backend->Hide(); minimized = False; Minimize(); } visible = True; visibilitySet = True; backend->Show(); onShow.Emit(); return Success(); } S::Int S::GUI::Window::Hide() { if (!visible) return Success(); if (created) backend->Hide(); visible = False; visibilitySet = True; onHide.Emit(); return Success(); } S::Int S::GUI::Window::Minimize() { if (minimized) return Success(); if (!created) { minimized = True; return Success(); } backend->Minimize(); return Success(); } S::Int S::GUI::Window::Maximize() { if (maximized) return Success(); if (!created) { maximized = True; return Success(); } backend->Maximize(); return Success(); } S::Int S::GUI::Window::Restore() { if (!maximized && !minimized) return Success(); if (!created) { maximized = False; minimized = False; return Success(); } backend->Restore(); return Success(); } S::Int S::GUI::Window::Raise() { if (created) backend->Raise(); return Success(); } S::GUI::Rect S::GUI::Window::GetWindowRect() const { return Rect(GetPosition(), GetSize()); } S::GUI::Rect S::GUI::Window::GetClientRect() const { return Rect(Point(innerOffset.left, innerOffset.top), GetSize() - Size(innerOffset.left + innerOffset.right, innerOffset.top + innerOffset.bottom)); } S::GUI::Rect S::GUI::Window::GetRestoredWindowRect() const { Rect restoredRect = backend->GetRestoredWindowRect(); if (restoredRect != Rect()) return restoredRect; return GetWindowRect(); } S::GUI::Rect S::GUI::Window::GetVisibleArea() const { return Rect(Point(frameWidth, frameWidth), GetRealSize() - Size(frameWidth, frameWidth) * 2); } S::Int S::GUI::Window::SetMinimumSize(const Size &newMinSize) { backend->SetMinimumSize(newMinSize); return Success(); } S::Int S::GUI::Window::SetMaximumSize(const Size &newMaxSize) { backend->SetMaximumSize(newMaxSize); return Success(); } S::Bool S::GUI::Window::Create() { if (!IsRegistered() || created) return False; #ifdef __WIN32__ if (flags & WF_NORESIZE) frameWidth = 4; #endif /* Check if there is a titlebar. */ flags |= WF_NOTITLE; for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); if (widget->GetObjectType() == Titlebar::classID) { flags ^= WF_NOTITLE; break; } } /* Open the new window. */ if (backend->Open(text, GetPosition(), GetSize(), flags) == Success()) { Surface *surface = GetDrawSurface(); surface->SetRightToLeft(IsRightToLeft()); visible = False; return True; } return False; } S::Int S::GUI::Window::WaitUntilClosed() { if (!IsRegistered()) return Error(); if (!created) Create(); if (!visible) Show(); /* Wait here until window is closed. */ System::EventProcessor event; while (!destroyed) event.ProcessNextEvent(); /* Sleep while Window is still in use. */ while (IsObjectInUse()) S::System::System::Sleep(10); return Success(); } S::Int S::GUI::Window::Close() { backend->RequestClose(); return Success(); } S::Void S::GUI::Window::OnCreate() { EnterProtectedRegion(); if (GetObjectType() != ToolWindow::classID) nOfActiveWindows++; created = True; CalculateOffsets(); onCreate.Emit(); } S::Void S::GUI::Window::OnDestroy() { destroyed = True; visible = False; if (GetObjectType() != ToolWindow::classID) nOfActiveWindows--; LeaveProtectedRegion(); } S::Void S::GUI::Window::OnMinimize() { minimized = True; } S::Void S::GUI::Window::OnMaximize() { maximized = True; } S::Void S::GUI::Window::OnRestore() { if (minimized) minimized = False; else if (maximized) maximized = False; } S::Int S::GUI::Window::Process(Int message, Int wParam, Int lParam) { if (!created) return MessageUnknown; EnterProtectedRegion(); /* Forward event to subscribers. */ onEvent.Emit(message, wParam, lParam); /* Process events we are interested in. */ Int rVal = MessageUnknown; switch (message) { case SM_GETFOCUS: if (!focussed) { focussed = True; onGetFocus.Emit(); } break; case SM_LOSEFOCUS: if (focussed) { Window *focusWnd = (Window *) Object::GetObject(wParam, Window::classID); if (focusWnd != NIL) { if (focusWnd->GetObjectType() == ToolWindow::classID && focusWnd->GetOrder() >= GetOrder()) { LeaveProtectedRegion(); return MessageProcessed; } } focussed = False; onLoseFocus.Emit(); } break; case SM_WINDOWMETRICS: { Point nPos((unsigned(wParam) >> 16) - 32768, (unsigned(wParam) & 65535) - 32768); Size nSize((unsigned(lParam) >> 16) - 32768, (unsigned(lParam) & 65535) - 32768); Bool moved = (GetPosition() != nPos); Bool resized = (GetSize() != nSize); if (moved || resized) { DeactivateTooltip(); InvalidateMetrics(); if (moved) { pos = nPos; onChangePosition.Emit(pos); } if (resized) { size = nSize; onChangeSize.Emit(size); } Bool prevVisible = visible; visible = False; if (resized) { CalculateOffsets(); updateRect = Rect(Point(-1, -1), Size(0, 0)); } visible = prevVisible; } } rVal = MessageProcessed; break; case SM_PAINT: { Bool resized = (updateRect == Rect(Point(-1, -1), Size(0, 0))); if (resized) updateRect = Rect(Point(0, 0), GetRealSize()); else updateRect = backend->GetUpdateRect(); Paint(resized ? SP_PAINT : SP_UPDATE); updateRect = Rect(Point(0, 0), GetRealSize()); } rVal = MessageProcessed; break; } if (rVal != MessageUnknown) { LeaveProtectedRegion(); return rVal; } /* Delegate event to main layer. */ if (mainLayer->Process(message, wParam, lParam) == MessageProcessed) { LeaveProtectedRegion(); return MessageProcessed; } /* Delegate event to other widgets. */ for (Int i = GetNOfObjects() - 1; i >= 0; i--) { Widget *object = GetNthObject(i); if (object == NIL || object == mainLayer) continue; if (object->Process(message, wParam, lParam) == MessageProcessed) { rVal = MessageProcessed; break; } } /* Invoke callback for application message handling. */ if (rVal == MessageUnknown) rVal = handleSystemMessage.Call(message, wParam, lParam); LeaveProtectedRegion(); return rVal; } S::Int S::GUI::Window::Paint(Int message) { if (!IsRegistered()) return Error(); if (!created) return Success(); if (!IsVisible()) return Success(); if (updateRect.GetWidth() == 0 || updateRect.GetHeight() == 0) return Success(); EnterProtectedRegion(); Surface *surface = GetDrawSurface(); #ifdef __WIN32__ static Bool flatStyle = Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2); #else static Bool flatStyle = True; #endif Size realSize = GetRealSize(); Float fontSize = surface->GetSurfaceDPI() / 96.0; if (updateRect.left < frameWidth) updateRect.left = frameWidth - 1; if (updateRect.top < frameWidth) updateRect.top = frameWidth - 1; if (realSize.cx - updateRect.right < frameWidth) updateRect.right = realSize.cx - frameWidth + 1; if (realSize.cy - updateRect.bottom < frameWidth) updateRect.bottom = realSize.cy - frameWidth + 1; Rect workArea = System::Screen::GetVirtualScreenMetrics(); if (message == SP_UPDATE && GetPosition().x > workArea.left - 2 && GetPosition().y > workArea.top - 2 && GetPosition().x + GetSize().cx < workArea.right + 2 && GetPosition().y + GetSize().cy < workArea.bottom + 2) { surface->PaintRect(updateRect); } else { RightToLeftModifier rightToLeft; rightToLeft.SetSurfaceSize(surface->GetSize()); rightToLeft.SetRightToLeft(IsRightToLeft()); surface->StartPaint(rightToLeft.TranslateRect(updateRect)); surface->Box(updateRect, Setup::BackgroundColor, Rect::Filled); if (type != ToolWindow::classID) { Widget *lastTopWidget = NIL; Int topoffset = frameWidth; Int positions = 0; for (Int i = 0; i < GetNOfObjects(); i++) { Widget *object = GetNthObject(i); positions |= object->GetOrientation(); if (object->GetOrientation() == OR_TOP) { lastTopWidget = object; if (object->subtype == WO_SEPARATOR) { topoffset += object->GetSize().cy + 3; Point p1 = Point(frameWidth * fontSize, topoffset * fontSize - 2); Point p2 = Point(realSize.cx - frameWidth, p1.y); #ifndef __APPLE__ if (!flatStyle && icon != NIL) p1.x += Math::Round(18 * fontSize); #endif surface->Bar(p1, p2, OR_HORZ); } else { topoffset += object->GetSize().cy; } } } if (positions & OR_TOP) { Point p1 = Point(frameWidth, topoffset * fontSize - 2); Point p2 = Point(realSize.cx - frameWidth, p1.y); if (lastTopWidget != NIL && lastTopWidget->subtype == WO_NOSEPARATOR) { p1.y += Math::Round(3 * surface->GetSurfaceDPI() / 96.0); p2.y += Math::Round(3 * surface->GetSurfaceDPI() / 96.0); } surface->Bar(p1, p2, OR_HORZ); surface->Bar(p1 + Point(0, 2), p2 + Point(0, 2), OR_HORZ); } if (positions & OR_BOTTOM) { Point p1 = Point(frameWidth, realSize.cy - innerOffset.bottom * fontSize + 1); Point p2 = Point(realSize.cx - frameWidth, p1.y); surface->Bar(p1, p2, OR_HORZ); surface->Bar(p1 + Point(0, 2), p2 + Point(0, 2), OR_HORZ); } if (positions & OR_LEFT) { Point p1 = Point(innerOffset.left * fontSize - 3, innerOffset.top); Point p2 = Point(p1.x, realSize.cy - innerOffset.bottom - 1); surface->Bar(p1, p2, OR_VERT); } if (positions & OR_RIGHT) { Point p1 = Point(realSize.cx - innerOffset.right * fontSize + 1, innerOffset.top); Point p2 = Point(p1.x, realSize.cy - innerOffset.bottom - 1); surface->Bar(p1, p2, OR_VERT); } } for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); if (widget->GetObjectType() != Layer::classID && widget->IsAffected(updateRect)) widget->Paint(SP_PAINT); } for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); if (widget->GetObjectType() == Layer::classID && widget->IsAffected(updateRect)) widget->Paint(SP_PAINT); } onPaint.Emit(); surface->EndPaint(); } LeaveProtectedRegion(); return Success(); } S::Void S::GUI::Window::CalculateOffsets() { Widget *lastTopWidget = NIL; Int positions = 0; innerOffset = Rect(Point(frameWidth, frameWidth), Size(0, 0)); for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); positions |= widget->GetOrientation(); if (widget->GetOrientation() == OR_TOP) { lastTopWidget = widget; widget->SetMetrics(Point(innerOffset.left, innerOffset.top), Size(GetWidth() - innerOffset.left - innerOffset.right, widget->GetHeight())); innerOffset.top += widget->GetHeight(); if (widget->subtype == WO_SEPARATOR) innerOffset.top += 3; } else if (widget->GetOrientation() == OR_BOTTOM) { widget->SetMetrics(Point(innerOffset.left, GetHeight() - innerOffset.bottom - widget->GetHeight()), Size(GetWidth() - innerOffset.left - innerOffset.right, widget->GetHeight())); innerOffset.bottom += widget->GetHeight(); } } if (positions & OR_TOP) innerOffset.top += 3; if (positions & OR_BOTTOM) innerOffset.bottom += 5; if (lastTopWidget != NIL) innerOffset.top += (lastTopWidget->subtype == WO_NOSEPARATOR ? 3 : 0); for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); if (widget->GetOrientation() == OR_LEFT) { widget->SetMetrics(Point(innerOffset.left, innerOffset.top), Size(widget->GetWidth(), GetHeight() - innerOffset.top - innerOffset.bottom)); innerOffset.left += widget->GetWidth(); } else if (widget->GetOrientation() == OR_RIGHT) { widget->SetMetrics(Point(GetWidth() - innerOffset.right - widget->GetWidth(), innerOffset.top), Size(widget->GetWidth(), GetHeight() - innerOffset.top - innerOffset.bottom)); innerOffset.right += widget->GetWidth(); } } if (positions & OR_LEFT) innerOffset.left += 3; if (positions & OR_RIGHT) innerOffset.right += 3; for (Int i = 0; i < GetNOfObjects(); i++) { Widget *widget = GetNthObject(i); if (widget->GetOrientation() == OR_CENTER) { widget->SetMetrics(Point(innerOffset.left, innerOffset.top), Size(GetWidth() - innerOffset.left - innerOffset.right, GetHeight() - innerOffset.top - innerOffset.bottom)); widget->SetOrientation(OR_CENTER); } } } const S::GUI::Size &S::GUI::Window::GetSizeModifier() const { return backend->GetSizeModifier(); } S::GUI::Point S::GUI::Window::GetMousePosition() const { Point position = Input::Pointer::GetPosition(); if (IsRightToLeft()) position = Point(GetRealSize().cx - (position.x - GetX()) - 1, position.y - GetY()); else position -= GetPosition(); return position; } S::Bool S::GUI::Window::IsMouseOn(const Rect &rect) const { Surface *surface = GetDrawSurface(); if (surface->GetSystemSurface() == NIL) return False; Point mousePos = GetMousePosition(); if ((mousePos.x >= rect.left) && (mousePos.x < rect.right) && (mousePos.y >= rect.top) && (mousePos.y < rect.bottom)) { if (Input::Pointer::GetPointerWindow() != this) return False; else return True; } return False; } S::GUI::Surface *S::GUI::Window::GetDrawSurface() const { return backend->GetDrawSurface(); } S::Void *S::GUI::Window::GetSystemWindow() const { return backend->GetSystemWindow(); } S::Int S::GUI::Window::Add(Widget *widget) { if (widget == NIL) return Error(); if (widget->GetOrientation() == OR_UPPERLEFT || widget->GetOrientation() == OR_UPPERRIGHT || widget->GetOrientation() == OR_LOWERLEFT || widget->GetOrientation() == OR_LOWERRIGHT) { if (mainLayer->Add(widget) == Success()) { /* Enable drag & drop if the added widget is a target. */ if (IsDropTarget()) backend->EnableDropFiles(True); return Success(); } return Error(); } if (Widget::Add(widget) == Success()) { /* Special handling for title and status bars. */ if (widget->GetObjectType() == Titlebar::classID) { if (!Binary::IsFlagSet(widget->GetFlags(), TB_MAXBUTTON)) flags |= WF_NORESIZE; if (widget->GetHeight() == 0) backend->SetSizeModifier(backend->GetSizeModifier() - Size(0, 19) * Surface().GetSurfaceDPI() / 96.0); } else if (widget->GetObjectType() == Statusbar::classID) { SetDefaultStatusText(widget->GetText()); } /* Recalculate offsets unless the added widget has free orientation. */ if (widget->GetOrientation() != OR_FREE) CalculateOffsets(); /* Enable drag & drop if the added widget is a target. */ if (IsDropTarget()) backend->EnableDropFiles(True); return Success(); } return Error(); } S::Int S::GUI::Window::Remove(Widget *widget) { if (widget == NIL) return Error(); if (widget->GetOrientation() == OR_UPPERLEFT || widget->GetOrientation() == OR_UPPERRIGHT || widget->GetOrientation() == OR_LOWERLEFT || widget->GetOrientation() == OR_LOWERRIGHT) { if (mainLayer->Remove(widget) == Success()) { /* Disable drag & drop if the removed widget was a target. */ if (!IsDropTarget()) backend->EnableDropFiles(False); return Success(); } return Error(); } if (Widget::Remove(widget) == Success()) { /* Recalculate offsets unless the removed widget had free orientation. */ if (widget->GetOrientation() != OR_FREE) CalculateOffsets(); /* Disable drag & drop if the removed widget was a target. */ if (!IsDropTarget()) backend->EnableDropFiles(False); return Success(); } return Error(); } S::GUI::Window *S::GUI::Window::GetWindow(Void *sysWindow) { if (sysWindow == NIL) return NIL; for (Int i = 0; i < windows.Length(); i++) { Window *window = windows.GetNth(i); if (window->GetSystemWindow() == sysWindow) return window; } return NIL; } smooth-0.9.11~git20260403.0230c0da/classes/i18n/000077500000000000000000000000001516402577000201745ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/i18n/Makefile000066400000000000000000000005331516402577000216350ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. # Enter object files here: OBJECTS = language.o number.o section.o translator.o translator_internal.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/i18n/language.cpp000077500000000000000000000034351516402577000224730ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2015 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::I18n::Language::Language() { rightToLeft = False; incomplete = False; } S::I18n::Language::~Language() { } S::Errors::Error S::I18n::Language::ParseHeader(XML::Node *language) { if (language == NIL) return Error(); XML::Node *info = language->GetNodeByName("info"); /* Return an error if we didn't find an info node. */ if (info == NIL) return Error(); for (Int i = 0; i < info->GetNOfNodes(); i++) { String property = info->GetNthNode(i)->GetAttributeByName("name")->GetContent(); if (property == "language") SetName(info->GetNthNode(i)->GetContent()); if (property == "righttoleft") rightToLeft = (info->GetNthNode(i)->GetContent() == "true" ? True : False); if (property == "encoding") encoding = info->GetNthNode(i)->GetContent(); if (property == "author") author = info->GetNthNode(i)->GetContent(); if (property == "url") url = info->GetNthNode(i)->GetContent(); if (property == "incomplete") incomplete = (info->GetNthNode(i)->GetContent() == "true" ? True : False); } return Success(); } S::Errors::Error S::I18n::Language::Parse(XML::Node *language) { if (language == NIL) return Error(); XML::Node *data = language->GetNodeByName("data"); /* Return an error if we didn't find a data node. */ if (data == NIL) return Error(); return Section::Parse(data); } smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/000077500000000000000000000000001516402577000216165ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_af.h000066400000000000000000000045551516402577000237570ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_AF #define H_OBJSMOOTH_I18N_AF static const char *smooth_af = " \ \ \ smooth \ Afrikaans \ false \ UTF-8 \ \ \ Reg \ Kanselleer \ Ja \ Nee \ Probeer weer \ Staak \ Ignoreer \ \ Herstel \ Knip \ Kopie \ Plak \ Maak skoon \ Kies alle \ \ Open lÃĒer \ Stoor lÃĒer \ Stoor lÃĒer as \ Kies gids \ Kies skrif tipe \ \ Kies kleur \ HTML-kode \ \ Leidraad van die dag \ Het jy geweet... \ Vertoon leidrade tydens opstart \ Volgende \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_ar.h000066400000000000000000000051231516402577000237630ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_AR #define H_OBJSMOOTH_I18N_AR static const char *smooth_ar = " \ \ \ smooth \ Arabic / Ø§Ų„ØšØąØ¨ŲŠØŠ \ true \ UTF-8 \ \ \ %%1 \ ؟ \ \ Ų…ŲˆØ§ŲŲ‚ \ ØŖŲ„Øēؐ \ Ų†ØšŲ… \ Ų„Ø§ \ ØŖØšŲØ¯ Ø§Ų„Ų…Ø­Ø§ŲˆŲ„ØŠ \ ØŖØŦŲ‡Øļ \ ØĒØŦØ§Ų‡Ų„ \ \ ØĒØąØ§ØŦØš \ Ų‚Øĩ \ Ų†ØŗØŽ \ Ų„ØĩŲ‚ \ Ų…Ø­Ųˆ \ ا؎ØĒØą Ø§Ų„ŲƒŲ„ \ \ Ø§ŲØĒØ­ ؅؄؁ \ Ø§Ø­ŲØ¸ ؅؄؁ \ Ø§Ø­ŲØ¸ ؅؄؁ Ųƒâ€ \ ا؎ØĒØą Ų…ØŦŲ„Ø¯ \ ا؎ØĒØą Ø§Ų„ØŽØˇ \ \ ا؎ØĒØą Ų„ŲˆŲ† \ Ø§Ų„ŲƒŲˆØ¯ \ \ ØĒŲ„Ų…ŲŠØ­ØŠ Ø§Ų„ŲŠŲˆŲ… \ Ų‡Ų„ ØĒØšŲ„Ų… ØŖŲ†... \ Ø§ØšØąØļ Ø§Ų„Ų†ØĩاØĻØ­ ØšŲ†Ø¯ Ø¨Ø¯ØĄ Ø§Ų„ØĒØ´ØēŲŠŲ„ \ Ø§Ų„ØĒØ§Ų„ŲŠ \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_bg.h000066400000000000000000000051451516402577000237550ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_BG #define H_OBJSMOOTH_I18N_BG static const char *smooth_bg = " \ \ \ smooth \ Bulgarian / Đ‘ŅŠĐģĐŗĐ°Ņ€ŅĐēи \ false \ UTF-8 \ \ \ ОК \ ĐžŅ‚ĐēаС \ Да \ НĐĩ \ ĐŸĐžĐ˛Ņ‚ĐžŅ€ĐĩĐŊиĐĩ \ ĐŸŅ€ĐĩĐēŅŠŅĐ˛Đ°ĐŊĐĩ \ ĐŸŅ€ĐĩĐŊĐĩĐąŅ€ĐĩĐŗĐ˛Đ°ĐŊĐĩ \ \ ĐžŅ‚ĐŧŅĐŊа \ Đ˜ĐˇŅ€ŅĐˇĐ˛Đ°ĐŊĐĩ \ КоĐŋĐ¸Ņ€Đ°ĐŊĐĩ \ ĐŸĐžŅŅ‚Đ°Đ˛ŅĐŊĐĩ \ Đ˜ĐˇŅ‡Đ¸ŅŅ‚Đ˛Đ°ĐŊĐĩ \ ĐœĐ°Ņ€ĐēĐ¸Ņ€Đ°ĐŊĐĩ ĐŊа Đ˛ŅĐ¸Ņ‡ĐēĐž \ \ ĐžŅ‚Đ˛Đ°Ņ€ŅĐŊĐĩ ĐŊа Ņ„Đ°ĐšĐģ \ ЗаĐŋĐ¸Ņ ĐŊа Ņ„Đ°ĐšĐģ \ ЗаĐŋĐ¸Ņ ĐŊа Ņ„Đ°ĐšĐģ ĐēĐ°Ņ‚Đž \ Đ˜ĐˇĐąĐžŅ€ ĐŊа Đ´Đ¸Ņ€ĐĩĐēŅ‚ĐžŅ€Đ¸Ņ \ Đ˜ĐˇĐąĐžŅ€ ĐŊа ŅˆŅ€Đ¸Ņ„Ņ‚ \ \ Đ˜ĐˇĐąĐžŅ€ ĐŊа Ņ†Đ˛ŅŅ‚ \ HTML ĐēОд \ \ ĐĄŅŠĐ˛ĐĩŅ‚ Са Đ´ĐĩĐŊŅ \ ЗĐŊаĐĩŅ‚Đĩ Đģи, ҇Đĩ... \ ПоĐēаСваĐŊĐĩ ĐŋŅ€Đ¸ ŅŅ‚Đ°Ņ€Ņ‚Đ¸Ņ€Đ°ĐŊĐĩ \ ĐĄĐģĐĩĐ´Đ˛Đ°Ņ‰ \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_ca.h000066400000000000000000000064121516402577000237460ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2024 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_CA #define H_OBJSMOOTH_I18N_CA static const char *smooth_ca = " \ \ \ smooth \ Catalan / Català \ false \ UTF-8 \ \ \ D'acord \ Cancel¡la \ Sí \ No \ Reintenta \ Interromp \ Ignora \ \ DesfÊs \ Talla \ Copia \ Enganxa \ Neteja \ Selecciona-ho tot \ \ RetrocÊs \ Tab \ Retorn \ Esc \ Espai \ RePàg \ AvPàg \ Fi \ Inici \ Esquerra \ Amunt \ Dreta \ Avall \ Ins \ Supr \ Ctrl \ Alt \ MajÃēs \ \ Obre un fitxer \ Desa el fitxer \ Desa el fitxer com a \ Seleccioneu un directori \ Seleccioneu el tipus de lletra \ \ SelecciÃŗ de color \ Codi HTML \ \ Consell del dia \ Sabíeu que... \ Mostra consells en iniciar \ SegÃŧent consell \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_ca@valencia.h000066400000000000000000000064151516402577000255540ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_CA_VALENCIA #define H_OBJSMOOTH_I18N_CA_VALENCIA static const char *smooth_ca_valencia = " \ \ \ smooth \ Valencian / Valencià \ false \ UTF-8 \ \ \ BÊ \ Cancel¡la \ Sí \ No \ Reintenta \ Interromp \ Ignora \ \ DesfÊs \ Talla \ Copia \ Apega \ Neteja \ Selecciona-ho tot \ \ RetrocÊs \ Tab \ Retorn \ Esc \ Espai \ RePàg \ AvPàg \ Fi \ Inici \ Esquerra \ Amunt \ Dreta \ Avall \ Ins \ Supr \ Ctrl \ Alt \ Maj \ \ Obri fitxer \ Guarda el fitxer \ Guarda el fitxer com a \ SelecciÃŗ de carpeta \ Trieu el tipus de lletra \ \ SelecciÃŗ de color \ Codi HTML \ \ Pista del dia \ Sabíeu que... \ Mostra pistes en engegar \ SegÃŧent \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_co.h000066400000000000000000000071621516402577000237670ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_CO #define H_OBJSMOOTH_I18N_CO static const char *smooth_co = " \ \ \ smooth \ Corsican / Corsu \ false \ UTF-8 \ \ \ Vai \ Abbandunà \ SÃŦ \ NÃ˛ \ Torna \ Interrompe \ Ignurà \ \ Disfà \ Taglià \ Cupià \ Incullà \ Viutà \ Tuttu selezziunà \ \ Currezzione \ Tab \ Entrata \ Scap \ Spaziu \ Pag. sÚ \ Pag. ghjÃ˛ \ Fine \ Accolta \ Manca \ InsÚ \ Diritta \ InghjÃ˛ \ Fram \ Squas \ Ctrl \ Alt \ Maius \ \ Apre u schedariu \ Arregistrà u schedariu \ Arregistrà u schedariu cÚ u nome \ Selezziunà u cartulare \ Selezziunà a grafia \ \ Selezziunà u culore \ Codice HTML \ R \ V \ T \ T \ S \ V \ \ Astuzia oghjinca \ A sapete chÃŦâ€Ļ \ Affissà l’astuzie à u lanciu \ Astuzia seguente \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_cs.h000066400000000000000000000051501516402577000237660ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_CS #define H_OBJSMOOTH_I18N_CS static const char *smooth_cs = " \ \ \ smooth \ Czech / Česky \ false \ UTF-8 \ \ \ OK \ ZruÅĄit \ Ano \ Ne \ Zkusit znovu \ PřeruÅĄit \ Ignorovat \ \ Zpět \ Vyjmout \ Kopírovat \ VloÅžit \ VyprÃĄzdnit \ Vybrat vÅĄe \ \ Mezerník \ Vlevo \ Nahoru \ Vpravo \ Dolů \ \ Otevřít soubor \ UloÅžit soubor \ UloÅžit soubor jako \ Vybrat sloÅžku \ Vybrat písmo \ \ Vyberte barvu \ HTML kÃŗd \ \ Tip dne \ Věděli jste... \ Zobrazovat při spuÅĄtění \ DalÅĄÃ­ \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_da.h000066400000000000000000000053211516402577000237450ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_DA #define H_OBJSMOOTH_I18N_DA static const char *smooth_da = " \ \ \ smooth \ Danish / Dansk \ false \ UTF-8 \ \ \ O.k. \ AnnullÊr \ Ja \ Nej \ Forsøg igen \ Afbryd \ IgnorÊr \ \ Fortryd \ Klip \ KopiÊr \ IndsÃĻt \ Ryd \ MarkÊr alt \ \ Backspace \ Tab \ Retur \ Esc \ Mellemrum \ Venstre \ Op \ Højre \ Ned \ \ Åbn fil \ Gem fil \ Gem fil som \ VÃĻlg mappe \ VÃĻlg skrifttype \ \ VÃĻlg farve \ HTML-kode \ \ Dagens tip \ Vidste du... \ Vis tip ved opstart \ NÃĻste \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_de.h000066400000000000000000000066571516402577000237660ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_DE #define H_OBJSMOOTH_I18N_DE static const char *smooth_de = " \ \ \ smooth \ German / Deutsch \ false \ UTF-8 \ \ \ OK \ Abbrechen \ Ja \ Nein \ Wiederholen \ Abbrechen \ Ignorieren \ \ RÃŧckgängig \ Ausschneiden \ Kopieren \ EinfÃŧgen \ LÃļschen \ Alles auswählen \ \ RÃŧcktaste \ Tab \ Eingabe \ Esc \ Leertaste \ Bild auf \ Bild ab \ Ende \ Pos1 \ Pfeil links \ Pfeil hoch \ Pfeil rechts \ Pfeil runter \ Einfg \ Entf \ Strg \ Alt \ Umschalt \ \ Datei Ãļffnen \ Datei speichern \ Datei speichern unter \ Verzeichnis auswählen \ Schriftart auswählen \ \ Farbauswahl \ HTML-Code \ F \ S \ H \ \ Tipp des Tages \ Wussten Sie schon... \ Tipps beim Start anzeigen \ Nächster Tipp \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_el.h000066400000000000000000000055601516402577000237660ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_EL #define H_OBJSMOOTH_I18N_EL static const char *smooth_el = " \ \ \ smooth \ Greek / ΕÎģÎģΡÎŊΚÎēÎŦ \ false \ UTF-8 \ \ \ ΕÎŊĪ„ÎŦΞÎĩΚ \ ΑÎēĪĪĪ‰ĪƒÎˇ \ Ναι \ ÎŒĪ‡Îš \ Î ĪÎŋĪƒĪ€ÎŦθÎĩΚι ΞιÎŊÎŦ \ Î•ÎŗÎēÎąĪ„ÎŦÎģÎĩÎšĪˆÎˇ \ Î ÎąĪÎŦβÎģÎĩĪˆÎˇ \ \ ΑÎŊÎąÎ¯ĪÎĩĪƒÎˇ \ Î‘Ī€ÎŋÎēÎŋĪ€ÎŽ \ ΑÎŊĪ„ÎšÎŗĪÎąĪ†ÎŽ \ Î•Ī€ÎšÎēΌÎģÎģÎˇĪƒÎˇ \ ÎšÎąÎ¸ÎąĪÎšĪƒÎŧĪŒĪ‚ \ Î•Ī€ÎšÎģÎŋÎŗÎŽ ΌÎģΉÎŊ \ \ Î‘ĪÎšĪƒĪ„Îĩ΁ÎŦ \ ΠÎŦÎŊΉ \ ΔÎĩΞΚÎŦ \ ΚÎŦ΄Ή \ \ ΆÎŊÎŋÎšÎŗÎŧÎą ÎąĪĪ‡ÎĩίÎŋĪ… \ Î‘Ī€ÎŋθΎÎēÎĩĪ…ĪƒÎˇ ÎąĪĪ‡ÎĩίÎŋĪ… \ Î‘Ī€ÎŋθΎÎēÎĩĪ…ĪƒÎˇ ÎąĪĪ‡ÎĩίÎŋĪ… Ή΂ \ Î•Ī€ÎšÎģÎŋÎŗÎŽ Ī†ÎąÎēέÎģÎŋĪ… \ Î•Ī€ÎšÎģÎŋÎŗÎŽ ÎŗĪÎąÎŧÎŧÎąĪ„Îŋ΃ÎĩÎšĪÎŦĪ‚ \ \ Î•Ī€ÎšÎģÎ­ÎžĪ„Îĩ Ī‡ĪĪŽÎŧÎą \ HTML ÎēĪŽÎ´ÎšÎēÎą \ \ ÎŖĪ…ÎŧβÎŋĪ…ÎģÎŽ Ī„ÎˇĪ‚ ΡÎŧÎ­ĪÎąĪ‚ \ ÎžÎ­ĪÎąĪ„Îĩ... \ ΕÎŧΆÎŦÎŊÎšĪƒÎˇ ĪƒĪ„ÎˇÎŊ ÎĩÎēÎēίÎŊÎˇĪƒÎˇ \ Î•Ī€ĪŒÎŧÎĩÎŊÎŋ \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_eo.h000066400000000000000000000064101516402577000237640ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_EO #define H_OBJSMOOTH_I18N_EO static const char *smooth_eo = " \ \ \ smooth \ Esperanto \ false \ UTF-8 \ \ \ Konfirmu \ Rezignu \ Jes \ Ne \ Reprovu \ Haltu \ Ignoru \ \ Malfari \ Eltondi \ Kopii \ Enmeti \ Forviŝi \ Elekti ĉion \ \ Retro \ Tab \ Konfirm \ Eskap \ Spac \ Paĝo supren \ Paĝo malsupren \ Fino \ Hejm \ Maldekstren \ Supren \ Dekstren \ Malsupren \ Enmet \ For \ Ktrl \ Alt \ Majuskl \ \ Malfermi dosieron \ Konservi dosieron \ Konservi dosieron kiel \ Elekti dosierujon \ Elekti tiparon \ \ Elekti koloron \ HTML-kodo \ \ Konsileto de la tago \ Ĉu vi sciis... \ Montri konsiletojn ĉe lanĉo \ Sekva konsileto \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_es.h000066400000000000000000000065141516402577000237750ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_ES #define H_OBJSMOOTH_I18N_ES static const char *smooth_es = " \ \ \ smooth \ Spanish / EspaÃąol \ false \ UTF-8 \ \ \ Aceptar \ Cancelar \ Sí \ No \ Reintentar \ Interrumpir \ Ignorar \ \ Deshacer \ Cortar \ Copiar \ Pegar \ Borrar \ Seleccionar todo \ \ Retroceso \ Tabulador \ Intro \ Esc \ Espacio \ RePÃĄg \ AvPÃĄg \ Fin \ Inicio \ Izquierda \ Arriba \ Derecha \ Abajo \ Insert \ Supr \ Ctrl \ Alt \ MayÃēsculas \ \ Abrir archivo \ Guardar archivo \ Guardar archivo como \ Seleccionar carpeta \ Seleccionar tipo de letra \ \ Seleccione un color \ CÃŗdigo HTML \ \ Sugerencia del día \ Sabía... \ Mostrar sugerencias al inicio \ Siguiente \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_et.h000066400000000000000000000051771516402577000240020ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_ET #define H_OBJSMOOTH_I18N_ET static const char *smooth_et = " \ \ \ smooth \ Estonian / Eesti \ false \ UTF-8 \ \ \ OK \ Loobu \ Jah \ Ei \ Proovi uuesti \ Katkesta \ Eira \ \ VÃĩta tagasi \ LÃĩika \ Kopeeri \ Aseta \ Puhasta \ Vali kÃĩik \ \ TÃŧhik \ Nool vasakule \ Nool Ãŧles \ Nool paremale \ Nool alla \ \ Faili avamine \ Faili salvestamine \ Faili salvestamine teise nimega \ Kataloogi valimine \ Fondi valik \ \ Värvi valimine \ HTML kood \ \ Päeva nÃĩuanne \ Kas sa teadsid... \ Näita käivitamisel \ Järgmine \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_eu.h000066400000000000000000000063201516402577000237720ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_EU #define H_OBJSMOOTH_I18N_EU static const char *smooth_eu = " \ \ \ smooth \ Basque / Euskara \ false \ ISO-8859-1 \ \ \ Ados \ Utzi \ Bai \ Ez \ Berriz saiatu \ Galarazi \ Ez ikusi egin \ \ Desegin \ Ebaki \ Kopiatu \ Itsatsi \ Garbitu \ Hautatu dena \ \ Atzera-tekla \ Tab \ Itzuli \ Ihes \ Zuriunea \ OrriGora \ OrriBehera \ Amaiera \ Hasiera \ Ezkerrera \ Gora \ Eskuinera \ Behera \ Txert \ Ezab \ Ktrl \ Alt \ Maius \ \ Ireki fitxategia \ Gorde fitxategia \ Gorde fitxategia honela \ Hautatu karpeta \ Hautatu letra-tipoa \ \ Hautatu kolorea \ HTML kode \ \ Eguneko aholkua \ Bazenekien... \ Erakutsi abioan \ Hurrengoa \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_fa.h000066400000000000000000000050521516402577000237500ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_FA #define H_OBJSMOOTH_I18N_FA static const char *smooth_fa = " \ \ \ smooth \ Farsi / ŲØ§ØąØŗÛŒ \ true \ UTF-8 \ \ \ ؟ \ \ ØĒØŖÛŒÛŒØ¯ \ Ų„Øē؈ \ Ø¨Ų„Ų‡ \ Ų†Ų‡ \ ØŗØšÛŒ Ų…ØŦدد \ Ų„Øē؈ \ Ú†Ø´Ų… ŲžŲˆØ´ŲŠ \ \ ŲˆØ§Ú¯ØąØ¯ \ Ø¨ØąØ´ \ ÚŠŲžŲŠ \ Ú†ØŗØ¨Ø§Ų†Ø¯Ų† \ ŲžØ§ÚŠ ÚŠØąØ¯Ų† \ Ø¨ØąÚ¯Ø˛ÛŒØ¯Ų† Ų‡Ų…Ų‡ \ \ Ø¨Ø§Ø˛ ÚŠØąØ¯Ų† ŲØ§ŲŠŲ„ \ Ø°ØŽÛŒØąÛ€ ŲØ§ŲŠŲ„ \ Ø°ØŽÛŒØąÛ€ ŲØ§ŲŠŲ„ Ø¨Ų‡ ØšŲ†ŲˆØ§Ų† \ Ø¨ØąÚ¯Ø˛ÛŒØ¯Ų† ŲžŲˆØ´Ų‡ \ Ø¨ØąÚ¯Ø˛ÛŒØ¯Ų† ŲŲˆŲ†ØĒ \ \ Ø¨ØąÚ¯Ø˛ÛŒØ¯Ų† ØąŲ†Ú¯ \ HTML ڊد \ \ Ų†ÚŠØĒۀ ØąŲˆØ˛ \ Øĸیا Ų…ÛŒâ€ŒØ¯Ø§Ų†ÛŒØ¯... \ Ų†Ų…Ø§ÛŒØ´ Ų†ÚŠØ§ØĒ Ų‡Ų†Ú¯Ø§Ų… ØąØ§Ų‡â€ŒØ§Ų†Ø¯Ø§Ø˛ÛŒ \ بؚدی \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_fi.h000066400000000000000000000053451516402577000237650ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_FI #define H_OBJSMOOTH_I18N_FI static const char *smooth_fi = " \ \ \ smooth \ Finnish / Suomi \ false \ UTF-8 \ \ \ OK \ Peruuta \ Kyllä \ Ei \ Yritä uudelleen \ Keskeytä \ Ohita \ \ Kumoa \ Leikkaa \ Kopioi \ Liitä \ Tyhjennä \ Valitse kaikki \ \ Askelpalautin \ VälilyÃļnti \ Vasen \ YlÃļs \ Oikea \ Alas \ \ Avaa tiedosto \ Tallenna tiedosto \ Tallenna tiedosto nimellä \ Valitse kansio \ Valitse kirjasin \ \ Valitse väri \ HTML-koodi \ \ Päivän vihje \ TiesitkÃļ... \ Näytä vihjeet käynnistyksen jälkeen \ Seuraava \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_fr.h000066400000000000000000000070221516402577000237700ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_FR #define H_OBJSMOOTH_I18N_FR static const char *smooth_fr = " \ \ \ smooth \ French / Français \ false \ UTF-8 \ \ \ OK \ Annuler \ Oui \ Non \ RÊessayer \ Interrompre \ Ignorer \ \ Annuler \ Couper \ Copier \ Coller \ Effacer \ Tout sÊlectionner \ \ Correction \ Tab. \ EntrÊe \ Échap. \ Espace \ Page prÊc \ Page suiv \ Fin \ DÊbut \ Gauche \ Haut \ Droite \ Bas \ Inser. \ Suppr. \ Ctrl \ Alt \ Maj \ \ Ouvrir un fichier \ Enregistrer le fichier \ Enregistrer le fichier sous \ Choisir un dossier \ Choisir une police \ \ Choisir une couleur \ Code HTML \ R \ V \ B \ T \ S \ V \ \ Astuce du jour \ Saviez-vous que... \ Afficher au dÊmarrage \ Suivant \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_gl.h000066400000000000000000000060461516402577000237700ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_GL #define H_OBJSMOOTH_I18N_GL static const char *smooth_gl = " \ \ \ smooth \ Galician / Galego \ false \ UTF-8 \ \ \ Aceptar \ Cancelar \ Si \ Non \ Tentar de novo \ Abortar \ Ignorar \ \ Desfacer \ Cortar \ Copiar \ Pegar \ Limpar \ Seleccionar todo \ \ Borrar \ Espacio \ Re. PÃĄx \ Av. PÃĄx \ Fin \ Inicio \ Esquerda \ Arriba \ Dereita \ Abaixo \ Insert \ Supr \ \ Abrir un ficheiro \ Gardar o ficheiro \ Gardar o ficheiro como \ Escoller un cartafol \ Escoller a fonte tipogrÃĄfica \ \ Escoller unha cor \ CÃŗdigo HTML \ \ Consello do día \ Sabía que... \ Mostrar os consellos ao iniciar \ Seguinte \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_he.h000066400000000000000000000046061516402577000237620ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_HE #define H_OBJSMOOTH_I18N_HE static const char *smooth_he = " \ \ \ smooth \ Hebrew / ×ĸברי×Ē \ true \ UTF-8 \ \ \ אישור \ ביטול \ כן \ לא \ נסה שוב \ ביטול \ ה×Ē×ĸלם \ \ בטל \ גזור \ ה×ĸ×Ē×§ \ הדבק \ נקה \ בחר הכל \ \ פ×Ēיח×Ē ×§×•×‘×Ĩ \ שמיר×Ē ×§×•×‘×Ĩ \ שמיר×Ē ×§×•×‘×Ĩ בשם \ בחיר×Ē ×Ą×¤×¨×™×™×” \ בחיר×Ē ×’×•×¤×Ÿ \ \ בחיר×Ē ×Ļב×ĸ \ קוד HTML \ \ ה×ĸ×Ļה היומי×Ē \ היד×ĸ×Ē... \ ה×Ļג ×ĸ×Ļו×Ē ×‘×ĸ×Ē ×”×”×¤×ĸלה \ הבא \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_hi.h000066400000000000000000000074011516402577000237620ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_HI #define H_OBJSMOOTH_I18N_HI static const char *smooth_hi = " \ \ \ smooth \ Hindi / ā¤šā¤ŋ⤍āĨā¤ĻāĨ€ \ false \ UTF-8 \ \ \ ⤠āĨ€ā¤• \ ⤰ā¤ĻāĨā¤Ļ ⤕⤰ \ ā¤š \ ā¤¨ā¤š \ ā¤Ģā¤ŋ⤰ ⤕āĨ‹ā¤ļā¤ŋā¤ļ ⤕⤰āĨ‡ā¤‚ \ ⤛āĨ‹ā¤Ąā¤ŧāĨ‡ā¤‚ \ ⤍⤜ā¤ŧ⤰⤅⤂ā¤Ļā¤žā¤œā¤ŧ ⤕⤰āĨ‡ā¤‚ \ \ ā¤Ēā¤šā¤˛āĨ‡ ⤜āĨˆā¤¸ā¤ž \ ā¤•ā¤žā¤Ÿ \ ⤍⤕ā¤ŧ⤞ \ ⤚ā¤ŋā¤Ēā¤•ā¤žā¤ \ ā¤¸ā¤žā¤Ģ ⤕⤰āĨ‡ā¤‚ \ ⤏⤭āĨ€ ā¤•ā¤ž ⤚⤝⤍ ⤕⤰āĨ‡ā¤‚ \ \ ā¤ŦāĨˆā¤•⤏āĨā¤ĒāĨ‡ā¤¸ \ ⤟āĨˆā¤Ŧ \ ⤰ā¤ŋ⤟⤰ \ ā¤ā¤¸āĨā¤•āĨ‡ā¤Ē \ ⤏āĨā¤ĒāĨ‡ā¤¸ \ ā¤ĒāĨ‡ā¤œ-⤅ā¤Ē \ ā¤ĒāĨ‡ā¤œ-ā¤Ąā¤žā¤‰ā¤¨ \ ā¤ā¤Ŗ \ ā¤šāĨ‹ā¤Ž \ ā¤Ŧā¤žā¤¯ā¤žā¤ \ ⤊ā¤Ē⤰ \ ā¤Ļā¤žā¤¯ \ ⤍āĨ€ā¤š \ ⤇⤂⤏⤰āĨā¤Ÿ \ ā¤Ąā¤ŋ⤞āĨ€ā¤Ÿ \ ā¤•ā¤‚ā¤ŸāĨā¤°āĨ‹ā¤˛ \ ⤑⤞ \ ā¤ļā¤ŋā¤ĢāĨā¤Ÿ \ \ ā¤Ģā¤ŧā¤žā¤‡ā¤˛ ⤖āĨ‹ā¤˛āĨ‡ā¤‚ \ ā¤Ģā¤ŧā¤žā¤‡ā¤˛ ā¤¸ā¤šāĨ‡ā¤œāĨ‡ā¤‚ \ ā¤Ģā¤ŧā¤žā¤‡ā¤˛ ⤇⤏ ⤰āĨā¤Ē ā¤ŽāĨ‡ā¤‚ ā¤¸ā¤šāĨ‡ā¤œāĨ‡ā¤‚ \ ā¤Ģā¤ŧāĨ‹ā¤˛āĨā¤Ąā¤° ⤚āĨā¤¨āĨ‡ā¤‚ \ ā¤Ģā¤ŧāĨ‰ā¤¨āĨā¤Ÿ ⤚āĨā¤¨āĨ‡ā¤‚ \ \ ⤰⤂⤗ ⤚āĨā¤¨āĨ‡ā¤‚ \ HTML ⤕āĨ‹ā¤Ą \ \ ā¤†ā¤œ ā¤•ā¤ž ⤍āĨā¤¸āĨā¤–ā¤ŧā¤ž \ ⤕āĨā¤¯ā¤ž ⤆ā¤Ē ā¤œā¤žā¤¨ā¤¤āĨ‡ ā¤šāĨˆā¤‚... \ ā¤ĒāĨā¤°ā¤žā¤°ā¤‚⤭ ā¤ŽāĨ‡ā¤‚ ⤍āĨā¤¸āĨā¤–ā¤ŧā¤ž ā¤Ļā¤ŋā¤–ā¤žā¤ā¤ \ ā¤…ā¤—ā¤˛ā¤ž \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_hr.h000066400000000000000000000051631516402577000237760ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_HR #define H_OBJSMOOTH_I18N_HR static const char *smooth_hr = " \ \ \ smooth \ Croatian / Hrvatski \ false \ UTF-8 \ \ \ Prihvati \ Zatvori \ Da \ Ne \ PokuÅĄaj ponovno \ Prekini \ Zanemari \ \ PoniÅĄti \ IzreÅži \ Kopiraj \ Zalijepi \ IzbriÅĄi \ Odaberi sve \ \ Razmaknica \ Lijevo \ Gore \ Desno \ Dolje \ \ Otvori dokument \ Spremi dokument \ Spremi dokument kao ... \ Odaberi mapu \ Odaberi font \ \ Izbor boje \ HTML kod \ \ Savjet dana \ Da li znate ... \ PokaÅži savjete na početku \ Sljedeći savjet \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_hu.h000066400000000000000000000054341516402577000240020ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_HU #define H_OBJSMOOTH_I18N_HU static const char *smooth_hu = " \ \ \ smooth \ Hungarian / Magyar \ false \ UTF-8 \ \ \ OK \ MÊgsem \ Igen \ Nem \ Újra \ MegszakítÃĄs \ Figyelmen kívÃŧl hagyÃĄs \ \ VisszavonÃĄs \ KivÃĄgÃĄs \ MÃĄsolÃĄs \ BeillesztÊs \ A mező(k) tÃļrlÊse \ Minden kijelÃļlÊse \ \ VisszalÊpÊs \ SzÃŗkÃļz \ Balra \ Fel \ Jobbra \ Le \ \ FÃĄjl megnyitÃĄsa \ A fÃĄjl mentÊse \ A fÃĄjl mentÊse mint \ Mappa kivÃĄlasztÃĄsa \ BetÅątípus kivÃĄlasztÃĄsa \ \ Szín kivÃĄlasztÃĄsa \ HTML kÃŗd \ \ A nap tippje \ Tudta, hogy... \ FelhasznÃĄlÃĄsi tipp indítÃĄskor \ KÃļvetkező \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_id.h000066400000000000000000000046101516402577000237550ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_ID #define H_OBJSMOOTH_I18N_ID static const char *smooth_id = " \ \ \ smooth \ Indonesian / Indonesia \ false \ ISO-8859-1 \ \ \ OK \ Batal \ Ya \ Tidak \ Ulangi \ Batalkan \ Abaikan \ \ Tak jadi \ Potong \ Salin \ Tempel \ Bersihkan \ Pilih semua \ \ Buka berkas \ Simpan berkas \ Simpan berkas sebagai \ Pilih direktori \ Pilih fonta \ \ Pilih warna \ Kode HTML \ \ Tip hari ini \ Apakah anda tahu... \ Tampilkan pada mulai hidupkan \ Berikutnya \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_it.h000066400000000000000000000064501516402577000240010ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_IT #define H_OBJSMOOTH_I18N_IT static const char *smooth_it = " \ \ \ smooth \ Italian / Italiano \ false \ UTF-8 \ \ \ OK \ Annulla \ SÃŦ \ No \ Riprova \ Interrompi \ Ignora \ \ Annulla \ Taglia \ Copia \ Incolla \ Pulisci \ Seleziona tutto \ \ Backspace \ Tab \ Invio \ Esc \ Spazio \ Pag su \ Pag giÚ \ Fine \ Inizio \ Sinistra \ Su \ Destra \ GiÚ \ Ins \ Canc \ Ctrl \ Alt \ Shift \ \ Apri file \ Salva file \ Salva file con nome \ Seleziona cartella \ Seleziona carattere \ \ Selezione colore \ Codice HTML \ \ Suggerimenti \ Non tutti sanno che... \ Mostra suggerimenti all'avvio \ Successivo \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_ja.h000066400000000000000000000052001516402577000237470ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_JA #define H_OBJSMOOTH_I18N_JA static const char *smooth_ja = " \ \ \ smooth \ Japanese / æ—ĨæœŦčĒž \ false \ UTF-8 \ \ \ OK \ ã‚­ãƒŖãƒŗã‚ģãƒĢ \ はい \ いいえ \ 再čŠĻ行 \ 中æ­ĸ \ į„ĄčĻ– \ \ 元ãĢæˆģす \ 切り取り \ ã‚ŗãƒ”ãƒŧ \ č˛ŧりäģ˜ã‘ \ クãƒĒã‚ĸ \ すずãĻ選択 \ \ åˇĻ \ 上 \ åŗ \ 下 \ \ ãƒ•ã‚Ąã‚¤ãƒĢを開く \ ãƒ•ã‚Ąã‚¤ãƒĢをäŋå­˜ã™ã‚‹ \ 名前をäģ˜ã‘ãĻãƒ•ã‚Ąã‚¤ãƒĢをäŋå­˜ã™ã‚‹ \ ãƒ‡ã‚ŖãƒŦクトãƒĒ選択 \ ãƒ•ã‚Šãƒŗãƒˆé¸æŠž \ \ ã‚Ģナãƒŧ選択 \ HTMLã‚ŗãƒŧド \ \ ä슿—ĨãŽãƒ’ãƒŗãƒˆ \ ご存įŸĨですか... \ čĩˇå‹•時ãĢį§˜č¨Ŗã‚’čĄ¨į¤ēする \ æŦĄãŽį§˜č¨Ŗ \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_ko.h000066400000000000000000000046501516402577000237760ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_KO #define H_OBJSMOOTH_I18N_KO static const char *smooth_ko = " \ \ \ smooth \ Korean / 한ęĩ­ė–´ \ false \ UTF-8 \ \ \ í™•ė¸ \ ėˇ¨ė†Œ \ 똈 \ ė•„ë‹ˆė˜¤ \ ë‹¤ė‹œ ė‹œë„ \ 뤑맀 \ ëŦ´ė‹œ \ \ ė‹¤í–‰ ėˇ¨ė†Œ \ ėž˜ëŧ내기 \ ëŗĩė‚Ŧ \ ëļ™ė—Ŧë„Ŗę¸° \ ė§€ėš°ę¸° \ ëĒ¨ë‘ ė„ íƒ \ \ ėŠ¤íŽ˜ė´ėŠ¤ \ \ 파ėŧ 뗴揰 \ 파ėŧ ė €ėžĨ \ 다ëĨ¸ 파ėŧė´ëĻ„ėœŧ로 ė €ėžĨ \ 폴더 ė„ íƒ \ 글ęŧ´ ė„ íƒ \ \ ėƒ‰ ė„ íƒ \ HTML ėŊ”드 \ \ ė˜¤ëŠ˜ė˜ 팁 \ ė•Œęŗ  ęŗ„ė‹­ë‹ˆęšŒ... \ ė‹œėž‘í•  때 팁 ëŗ´ę¸° \ ë‹¤ėŒ \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_lt.h000066400000000000000000000063571516402577000240120ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_LT #define H_OBJSMOOTH_I18N_LT static const char *smooth_lt = " \ \ \ smooth \ Lithuanian / LietuviÅŗ \ false \ UTF-8 \ \ \ Gerai \ AtÅĄaukti \ Taip \ Ne \ Bandyti vėl \ Nutraukti \ Ignoruoti \ \ AtÅĄaukti \ IÅĄkirpti \ Kopijuoti \ Padėti \ Valyti \ ÅŊymėti viską \ \ <–– \ Tab \ ÄŽvesti \ Gr \ Tarpas \ Psl.aukÅĄtyn \ Psl.Åžemyn \ Pabaiga \ PradÅžia \ Kairėn \ AukÅĄtyn \ DeÅĄinėn \ ÅŊemyn \ ÄŽterpti \ Å alinti \ Vald \ Alt \ Lyg2 \ \ Atverti failą \ ÄŽraÅĄyti failą \ ÄŽraÅĄyti failą kaip \ Pasirinkite aplanką \ Pasirinkti ÅĄriftą \ \ Pasirinkti spalvą \ HTML kodas \ \ Dienos patarimas \ Ar JÅĢs Åžinote... \ Rodyti paleidÅžiant \ Kitas \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_lv.h000066400000000000000000000054421516402577000240060ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_LV #define H_OBJSMOOTH_I18N_LV static const char *smooth_lv = " \ \ \ smooth \ Latvian / LatvieÅĄu \ false \ UTF-8 \ \ \ Labi \ Atcelt \ Jā \ Nē \ MēĪināt vēlreiz \ Pārtraukt \ Ignorēt \ \ Atcelt \ Griezt \ Kopēt \ IelÄĢmēt \ TÄĢrÄĢt \ Izvēlēties visus \ \ Ievads \ Atstarpe \ Beigas \ Mājas \ Pakreisi \ Uz augÅĄu \ Pa labi \ Uz leju \ \ Atvērt failu \ Saglabāt failu \ Saglabāt failu kā \ Izvēlēties mapi \ Izvēlēties fontu \ \ Izvēlieties krāsu \ HTML kods \ \ Dienas padoms \ Vai jÅĢs zināt... \ RādÄĢt pie palaiÅĄanas \ Nākamais \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_ms.h000066400000000000000000000050341516402577000240010ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_MS #define H_OBJSMOOTH_I18N_MS static const char *smooth_ms = " \ \ \ smooth \ Malay / Melayu \ false \ ISO-8859-1 \ \ \ OK \ Batal \ Ya \ Tidak \ Ulangi \ Tamat \ Abai \ \ Nyahcara \ Potong \ Salin \ Tepek \ Kosongkan \ Pilih semua \ \ Kiri \ Naik \ Kanan \ Turun \ \ Buka fail \ Simpan fail \ Simpan fail sebagai \ Pilih direktori \ Pilih font \ \ Pilih warna \ Kod HTML \ \ Petua hari ini \ Adakah anda tahu... \ Papar petua pada permulaan \ Berikutnya \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_nl.h000066400000000000000000000052421516402577000237740ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_NL #define H_OBJSMOOTH_I18N_NL static const char *smooth_nl = " \ \ \ smooth \ Dutch / Nederlands \ false \ UTF-8 \ \ \ OK \ Annuleren \ Ja \ Nee \ Opnieuw \ Afbreken \ Negeren \ \ Ongedaan maken \ Knippen \ KopiÃĢren \ Plakken \ Wissen \ Alles selecteren \ \ Spatie \ Links \ Omhoog \ Rechts \ Omlaag \ \ Bestand openen \ Bestand opslaan \ Bestand opslaan als \ Map selecteren \ Lettertype selecteren \ \ Kleur selecteren \ HTML-code \ \ Tip van de dag \ Wist u dat... \ Tips tonen tijdens het starten \ Volgende \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_no.h000066400000000000000000000050711516402577000237770ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_NO #define H_OBJSMOOTH_I18N_NO static const char *smooth_no = " \ \ \ smooth \ Norwegian / Norsk \ false \ UTF-8 \ \ \ OK \ Avbryt \ Ja \ Nei \ Prøv igjen \ Avbryt \ Overse \ \ Angre \ Klipp ut \ Kopier \ Lim inn \ Tøm \ Velg alt \ \ Rettetast \ Mellomrom \ Venstre \ Opp \ Høyre \ Ned \ \ Åpne fil \ Lagre fil \ Lagre fil som \ Velg mappe \ Velg skrift \ \ Velg farge \ HTML-kode \ \ Dagens tips \ Visste du... \ Vis ved oppstart \ Neste \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_pa.h000066400000000000000000000054451516402577000237700ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_PA #define H_OBJSMOOTH_I18N_PA static const char *smooth_pa = " \ \ \ smooth \ Punjabi / ā¨ĒāŠ°ā¨œā¨žā¨ŦāŠ€ \ false \ UTF-8 \ \ \ ā¨ āŠ€ā¨• ā¨šāŠˆ \ ā¨°āŠąā¨Ļ ā¨•ā¨°āŠ‹ \ ā¨šā¨žā¨‚ \ ā¨¨ā¨š \ ā¨ŽāŠāŠœ-ā¨•āŠ‹ā¨¸ā¨ŧā¨ŋ⍏ā¨ŧ \ ā¨›āŠąā¨ĄāŠ‹ \ ā¨…ā¨Ŗā¨Ąā¨ŋāŠąā¨  \ \ ā¨ĩā¨žā¨Ē⍏ \ ā¨•āŠąā¨Ÿ \ ⍍⍕⍞ \ ⍚ā¨ŋā¨Ēā¨•ā¨žā¨“ \ ā¨¸ā¨žāŠž \ ⍏⍭ ā¨šāŠā¨Ŗ \ \ ā¨–āŠąā¨Ŧ \ ā¨‰āŠąā¨¤āŠ‡ \ ā¨¸āŠąā¨œ \ ā¨šāŠ‡ā¨  \ \ ā¨Ģā¨žā¨‡ā¨˛ ā¨–āŠ‹ā¨˛ \ ā¨Ģā¨žā¨‡ā¨˛ ā¨¸āŠ°ā¨­ā¨žā¨˛āŠ‹ \ ā¨Ģā¨žā¨‡ā¨˛ ā¨‡āŠ°ā¨ ā¨¸āŠ°ā¨­ā¨žā¨˛āŠ‹ \ ā¨ĢāŠ‹ā¨˛ā¨Ąā¨° ā¨šāŠā¨Ŗ \ ā¨ĢāŠ‹ā¨‚ā¨Ÿ ā¨šāŠā¨Ŗ \ \ ā¨°āŠ°ā¨— ā¨šāŠā¨Ŗ \ HTML code \ \ ā¨…āŠąā¨œ ā¨Ļā¨ž ā¨¸āŠā¨ā¨žā¨… \ ā¨•āŠ€ ā¨¤āŠā¨¸āŠ€ā¨‚ ā¨œā¨žā¨Ŗā¨ĻāŠ‡ ā¨šāŠ‹... \ ā¨ļāŠā¨°āŠ‚ ā¨ĩāŠ‡ā¨˛āŠ‡ ⍟ā¨ŋāŠąā¨Ē ā¨ĩāŠ‡ā¨– \ ā¨…āŠąā¨—āŠ‡ \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_pl.h000066400000000000000000000054761516402577000240070ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_PL #define H_OBJSMOOTH_I18N_PL static const char *smooth_pl = " \ \ \ smooth \ Polish / Polski \ false \ UTF-8 \ \ \ OK \ Anuluj \ Tak \ Nie \ PowtÃŗrz \ Przerwij \ Ignoruj \ \ Cofnij \ Wytnij \ Kopiuj \ Wklej \ Wyczyść \ Zaznacz wszystko \ \ Cofnięcie \ Spacja \ Strona w gÃŗrę \ Strona w dÃŗÅ‚ \ W lewo \ W gÃŗrę \ W prawo \ W dÃŗÅ‚ \ \ OtwÃŗrz plik \ Zapisz plik \ Zapisz plik jako \ Wybierz katalog \ Wybierz czcionkę \ \ Wybierz kolor \ Kod HTML \ \ Porada dnia \ Czy wiesz, Åŧe... \ PokaÅŧ porady po uruchomieniu \ Następna \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_pt.h000066400000000000000000000051761516402577000240140ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_PT #define H_OBJSMOOTH_I18N_PT static const char *smooth_pt = " \ \ \ smooth \ Portuguese / PortuguÃĒs \ false \ UTF-8 \ \ \ OK \ Cancelar \ Sim \ NÃŖo \ Repetir \ Interromper \ Ignorar \ \ Desfazer \ Cortar \ Copiar \ Colar \ Limpar \ Seleccionar tudo \ \ Espaço \ Esquerda \ Cima \ Direita \ Baixo \ \ Abrir um ficheiro \ Gravar o ficheiro \ Gravar o ficheiro como \ Seleccionar a pasta \ Seleccione o tipo de letra \ \ Seleccionar a cor \ CÃŗdigo HTML \ \ Dica do dia \ Sabia que... \ Mostrar dicas no início \ Seguinte \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_pt_BR.h000066400000000000000000000052721516402577000243740ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_PT_BR #define H_OBJSMOOTH_I18N_PT_BR static const char *smooth_pt_BR = " \ \ \ smooth \ Portuguese (Brazilian) / PortuguÃĒs (Brasil) \ false \ UTF-8 \ \ \ OK \ Cancelar \ Sim \ NÃŖo \ Repetir \ Cancelar \ Ignorar \ \ Desfazer \ Cortar \ Copiar \ Colar \ Limpar \ Selecionar tudo \ \ Espaço \ Esquerda \ Acima \ Direita \ Abaixo \ \ Abrir arquivo \ Salvar arquivo \ Salvar arquivo como \ Selecionar pasta \ Selecionar fonte \ \ Selecionar cor \ CÃŗdigo HTML \ \ Dica do dia \ VocÃĒ sabia... \ Mostrar dicas na inicializaÃ§ÃŖo \ PrÃŗxima \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_ro.h000066400000000000000000000052521516402577000240040ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_RO #define H_OBJSMOOTH_I18N_RO static const char *smooth_ro = " \ \ \ smooth \ Romanian / RomÃĸnă \ false \ UTF-8 \ \ \ OK \ Renunță \ Da \ Nu \ ReÃŽncercare \ Anulare \ Ignorare \ \ Des-face \ Taie \ Copiază \ Lipeşte \ Şterge \ Selectează tot \ \ SpaÅŖiu \ StÃŽnga \ Sus \ Dreapta \ Jos \ \ Deschide fișierul \ Salvează fișierul \ Salvează fișierul ca \ Selectare culoare \ Selectare font \ \ Selectare culoare \ Codul HTML \ \ Sfatul zilei \ Știați că... \ Afișează sfatul zilei la pornire \ Următor \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_ru.h000066400000000000000000000054521516402577000240140ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2024 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_RU #define H_OBJSMOOTH_I18N_RU static const char *smooth_ru = " \ \ \ smooth \ Russian / Đ ŅƒŅŅĐēиК \ false \ UTF-8 \ \ \ OK \ ĐžŅ‚ĐŧĐĩĐŊа \ Да \ НĐĩŅ‚ \ ĐŸĐžĐ˛Ņ‚ĐžŅ€Đ¸Ņ‚ŅŒ \ ĐŸŅ€ĐĩŅ€Đ˛Đ°Ņ‚ŅŒ \ Đ˜ĐŗĐŊĐžŅ€Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ \ \ ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ \ Đ’Ņ‹Ņ€ĐĩĐˇĐ°Ņ‚ŅŒ \ КоĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ \ Đ’ŅŅ‚Đ°Đ˛Đ¸Ņ‚ŅŒ \ ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚ŅŒ \ Đ’Ņ‹Đ´ĐĩĐģĐ¸Ņ‚ŅŒ Đ˛ŅĐĩ \ \ ВĐģĐĩвО \ ВвĐĩҀ҅ \ ВĐŋŅ€Đ°Đ˛Đž \ ВĐŊиС \ \ ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ Ņ„Đ°ĐšĐģ \ ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚ŅŒ Ņ„Đ°ĐšĐģ \ ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚ŅŒ Ņ„Đ°ĐšĐģ ĐēаĐē ... \ Đ’Ņ‹ĐąĐžŅ€ ĐŋаĐŋĐēи \ Đ’Ņ‹ĐąĐžŅ€ ŅˆŅ€Đ¸Ņ„Ņ‚Đ° \ \ Đ’Ņ‹ĐąĐžŅ€ Ņ†Đ˛ĐĩŅ‚Đ° \ ĐēОд HTML \ \ ХОвĐĩŅ‚ Đ´ĐŊŅ \ ЗĐŊаĐĩŅ‚Đĩ Đģи Đ˛Ņ‹ ... \ ПоĐēĐ°ĐˇŅ‹Đ˛Đ°Ņ‚ŅŒ ĐŋŅ€Đ¸ СаĐŋ҃ҁĐēĐĩ \ ĐĄĐģĐĩĐ´ŅƒŅŽŅ‰Đ¸Đš \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_sk.h000066400000000000000000000052511516402577000240000ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_SK #define H_OBJSMOOTH_I18N_SK static const char *smooth_sk = " \ \ \ smooth \ Slovak / Slovenčina \ false \ UTF-8 \ \ \ OK \ ZruÅĄiÅĨ \ Áno \ Nie \ SkÃēsiÅĨ znova \ PreruÅĄiÅĨ \ IgnorovaÅĨ \ \ VrÃĄtiÅĨ späÅĨ \ VystrihnÃēÅĨ \ KopírovaÅĨ \ VloÅžiÅĨ \ VyčistiÅĨ \ VybraÅĨ vÅĄetko \ \ Medzera \ Šípka doÄžava \ Šípka hore \ Šípka doprava \ Šípka dole \ \ OtvoriÅĨ sÃēbor \ UloÅžiÅĨ sÃēbor \ UloÅžiÅĨ sÃēbor ako \ VybraÅĨ priečinok \ VybraÅĨ písmo \ \ VybraÅĨ farbu \ HTML kÃŗd \ \ Tip dňa \ Viete, Åže... \ ZobraziÅĨ tipy pri ÅĄtarte \ NasledujÃēci \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_sl.h000066400000000000000000000052471516402577000240060ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_SL #define H_OBJSMOOTH_I18N_SL static const char *smooth_sl = " \ \ \ smooth \ Slovenian / SlovenÅĄÄina \ false \ UTF-8 \ \ \ V redu \ Prekliči \ Da \ Ne \ Poskusi znova \ Prekini \ Prezri \ \ Razveljavi \ IzreÅži \ Kopiraj \ Prilepi \ Počisti \ Izberi vse \ \ Vračalka \ Preslednica \ Levo \ Gor \ Desno \ Dol \ \ Odpri datoteko \ Shrani datoteko \ Shrani datoteko kot \ Izberite mapo \ Izberite pisavo \ \ Izberite barvo \ HTML kodo \ \ Nasvet dneva \ Ali ste vedeli ... \ PokaÅži nasvete ob zagonu \ Naslednji \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_sr.h000066400000000000000000000051341516402577000240070ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_SR #define H_OBJSMOOTH_I18N_SR static const char *smooth_sr = " \ \ \ smooth \ Serbian / Srpski \ false \ UTF-8 \ \ \ Prihvati \ OtkaÅži \ Da \ Ne \ Ponovo pokuÅĄaj \ Prekini \ IgnoriÅĄi \ \ Opozovi \ Iseci \ Kopiraj \ Prenesi \ Očisti \ Izaberi sve \ \ Razmak \ Levo \ Gore \ Desno \ Dole \ \ Otvori fajl \ Sačuvaj fajl \ Sačuvaj fajl kao ... \ Odaberi folder \ Odaberi font \ \ Izbor boje \ HTML kod \ \ Savet dana \ Da li znate ... \ PokaÅži savete na početku \ Sledeći savet \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_sr@Cyrl.h000066400000000000000000000055251516402577000247450ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_SR_CYRL #define H_OBJSMOOTH_I18N_SR_CYRL static const char *smooth_sr_cyrl = " \ \ \ smooth \ Serbian / ĐĄŅ€ĐŋҁĐēи \ false \ UTF-8 \ \ \ ĐŸŅ€Đ¸Ņ…Đ˛Đ°Ņ‚Đ¸ \ ĐžŅ‚ĐēаĐļи \ Да \ НĐĩ \ ПоĐŊОвО ĐŋĐžĐēŅƒŅˆĐ°Ņ˜ \ ĐŸŅ€ĐĩĐēиĐŊи \ Đ˜ĐŗĐŊĐžŅ€Đ¸ŅˆĐ¸ \ \ ОĐŋОСОви \ Đ˜ŅĐĩŅ†Đ¸ \ КоĐŋĐ¸Ņ€Đ°Ņ˜ \ ĐŸŅ€ĐĩĐŊĐĩŅĐ¸ \ ĐžŅ‡Đ¸ŅŅ‚Đ¸ \ ИСайĐĩŅ€Đ¸ ŅĐ˛Đĩ \ \ РаСĐŧаĐē \ ЛĐĩвО \ Đ“ĐžŅ€Đĩ \ ДĐĩҁĐŊĐž \ ДоĐģĐĩ \ \ ĐžŅ‚Đ˛ĐžŅ€Đ¸ Ņ„Đ°Ņ˜Đģ \ ĐĄĐ°Ņ‡ŅƒĐ˛Đ°Ņ˜ Ņ„Đ°Ņ˜Đģ \ ĐĄĐ°Ņ‡ŅƒĐ˛Đ°Ņ˜ Ņ„Đ°Ņ˜Đģ ĐēаО ... \ ОдабĐĩŅ€Đ¸ Ņ„ĐžĐģĐ´ĐĩŅ€ \ ОдабĐĩŅ€Đ¸ Ņ„ĐžĐŊŅ‚ \ \ Đ˜ĐˇĐąĐžŅ€ ĐąĐžŅ˜Đĩ \ ĐĨĐĸМЛ ĐēОд \ \ ХавĐĩŅ‚ даĐŊа \ Да Đģи СĐŊĐ°Ņ‚Đĩ ... \ ПоĐēаĐļи ŅĐ°Đ˛ĐĩŅ‚Đĩ ĐŊа ĐŋĐžŅ‡ĐĩŅ‚Đē҃ \ ĐĄĐģĐĩĐ´ĐĩŅ›Đ¸ ŅĐ°Đ˛ĐĩŅ‚ \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_sv.h000066400000000000000000000064371516402577000240220ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_SV #define H_OBJSMOOTH_I18N_SV static const char *smooth_sv = " \ \ \ smooth \ Swedish / Svenska \ false \ UTF-8 \ \ \ OK \ Avbryt \ Ja \ Nej \ FÃļrsÃļk igen \ Avbryt \ Ignorera \ \ Ångra \ Klipp ut \ Kopiera \ Klistra in \ TÃļm \ Markera alla \ \ Backsteg \ Tabulator \ Retur \ Esc \ Mellanslag \ PgUp \ PgDn \ End \ Home \ Vänsterpil \ UppÃĨtpil \ HÃļgerpil \ NedÃĨtpil \ Ins \ Del \ Ctrl \ Alt \ Skift \ \ Öppna fil \ Spara fil \ Spara fil som \ Välj katalog \ Välj teckensnitt \ \ Välj färg \ HTML-kod \ F \ S \ H \ \ Dagens tips \ Visste du ... \ Visa tips vid start \ Nästa tips \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_th.h000066400000000000000000000057501516402577000240020ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_TH #define H_OBJSMOOTH_I18N_TH static const char *smooth_th = " \ \ \ smooth \ Thai / ā¸ ā¸˛ā¸Šā¸˛āš„ā¸—ā¸ĸ \ false \ UTF-8 \ \ \ ⏕⏁ā¸Ĩ⏇ \ ā¸ĸā¸āš€ā¸Ĩ⏴⏁ \ āšƒā¸Šāšˆ \ āš„ā¸Ąāšˆāšƒā¸Šāšˆ \ ā¸Ĩā¸­ā¸‡āšƒā¸Ģā¸Ą \ āš€ā¸Ĩ⏴⏁⏗⏺ \ āš„ā¸Ąāšˆā¸Ēā¸™āšƒā¸ˆ \ \ āš€ā¸Ĩ⏴⏁⏗ \ ā¸•ā¸ąā¸” \ ā¸„ā¸ąā¸”ā¸Ĩ⏭⏁ \ ⏧⏞⏇ \ ā¸Ĩāš‰ā¸˛ā¸‡ \ āš€ā¸Ĩā¸ˇā¸­ā¸ā¸—ā¸ąāš‰ā¸‡ā¸Ģā¸Ąā¸” \ \ āš€ā¸„ā¸˛ā¸°ā¸§ā¸Ŗā¸Ŗā¸„ \ ā¸‹āš‰ā¸˛ā¸ĸ \ ⏂ā¸ļāš‰ā¸™ \ ⏂⏧⏞ \ ā¸Ĩ⏇ \ \ āš€ā¸›ā¸´ā¸”āšā¸Ÿāš‰ā¸Ą \ ā¸šā¸ąā¸™ā¸—ā¸ļā¸āšā¸Ÿāš‰ā¸Ą \ ā¸šā¸ąā¸™ā¸—ā¸ļā¸āšā¸Ÿāš‰ā¸Ąāš€ā¸›āš‡ā¸™ \ āš€ā¸Ĩā¸ˇā¸­ā¸āš‚ā¸Ÿā¸Ĩāš€ā¸”ā¸­ā¸Ŗ \ āš€ā¸Ĩā¸ˇā¸­ā¸āšā¸šā¸šā¸­ā¸ąā¸ā¸Šā¸Ŗ \ \ āš€ā¸Ĩ⏎⏭⏁ā¸Ēā¸ĩ \ ⏪ā¸Ģā¸ąā¸Ē HTML \ \ āš€ā¸„ā¸Ĩāš‡ā¸”ā¸Ĩā¸ąā¸šā¸›ā¸Ŗā¸°ā¸ˆā¸ŗā¸§ā¸ąā¸™ \ ā¸„ā¸¸ā¸“ā¸—ā¸Ŗā¸˛ā¸šā¸Ģā¸Ŗā¸ˇā¸­āš„ā¸Ąāšˆā¸§āšˆā¸˛... \ āšā¸Ēā¸”ā¸‡āš€ā¸„ā¸Ĩāš‡ā¸”ā¸Ĩā¸ąā¸šāš€ā¸Ąā¸ˇāšˆā¸­āš€ā¸Ŗā¸´āšˆā¸Ąā¸—ā¸ŗā¸‡ā¸˛ā¸™ \ ā¸–ā¸ąā¸”āš„ā¸› \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_tr.h000066400000000000000000000054571516402577000240200ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_TR #define H_OBJSMOOTH_I18N_TR static const char *smooth_tr = " \ \ \ smooth \ Turkish / TÃŧrkçe \ false \ UTF-8 \ \ \ Tamam \ İptal \ Evet \ HayÄąr \ Yeniden Dene \ İptal \ Yoksay \ \ Geri al \ Kes \ Kopyala \ YapÄąÅŸtÄąr \ Temizle \ Hepsini seç \ \ Sil \ Boşluk \ Sol \ YukarÄą \ Sağ \ Aşağı \ Ins \ Sil \ \ Dosya aç \ DosyayÄą kaydet \ DosyayÄą farklÄą kaydet \ Dizin seç \ YazÄą Tipi seç \ \ Renk seç \ HTML kodu \ \ GÃŧnÃŧn İpucu \ Biliyor muydunuz... \ BaşlangÄąÃ§ta ipuçlarÄąnÄą gÃļster \ İleri \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_uk.h000066400000000000000000000056741516402577000240130ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_UK #define H_OBJSMOOTH_I18N_UK static const char *smooth_uk = " \ \ \ smooth \ Ukrainian / ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа \ false \ UTF-8 \ \ \ Đ“Đ°Ņ€Đ°ĐˇĐ´ \ ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ \ ĐĸаĐē \ ĐŅ– \ ĐĄĐŋŅ€ĐžĐąŅƒĐ˛Đ°Ņ‚Đ¸ ҉Đĩ Ņ€Đ°Đˇ \ ПĐĩŅ€ĐĩŅ€Đ˛Đ°Ņ‚Đ¸ \ Đ†ĐŗĐŊĐžŅ€ŅƒĐ˛Đ°Ņ‚Đ¸ \ \ ВĐĩŅ€ĐŊŅƒŅ‚Đ¸ \ Đ’Đ¸Ņ€Ņ–ĐˇĐ°Ņ‚Đ¸ \ ĐĄĐēĐžĐŋŅ–ŅŽĐ˛Đ°Ņ‚Đ¸ \ Đ’ŅŅ‚Đ°Đ˛Đ¸Ņ‚Đ¸ \ ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ \ Đ’Đ¸ĐąŅ€Đ°Ņ‚Đ¸ Đ˛ŅĐĩ \ \ ĐŸŅ€ĐžĐŋ҃ҁĐē \ ĐĄŅ‚Ņ€Ņ–ĐģĐēа ĐģŅ–Đ˛ĐžŅ€ŅƒŅ‡ \ ĐĄŅ‚Ņ€Ņ–ĐģĐēа Đ˛ĐŗĐžŅ€Ņƒ \ ĐĄŅ‚Ņ€Ņ–ĐģĐēа ĐŋŅ€Đ°Đ˛ĐžŅ€ŅƒŅ‡ \ ĐĄŅ‚Ņ€Ņ–ĐģĐēа вĐŊиС \ \ Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ Ņ„Đ°ĐšĐģ \ ЗбĐĩŅ€ĐĩĐŗŅ‚Đ¸ Ņ„Đ°ĐšĐģ \ ЗбĐĩŅ€ĐĩĐŗŅ‚Đ¸ Ņ„Đ°ĐšĐģ ŅĐē \ ВибĐĩŅ€Ņ–Ņ‚ŅŒ ĐēĐ°Ņ‚Đ°ĐģĐžĐŗ \ ВибĐĩŅ€Ņ–Ņ‚ŅŒ ŅˆŅ€Đ¸Ņ„Ņ‚ \ \ ВибĐĩŅ€Ņ–Ņ‚ŅŒ ĐēĐžĐģŅ–Ņ€ \ HTML ĐēОд \ \ ĐŸĐžŅ€Đ°Đ´Đ° Đ´ĐŊŅ \ Чи СĐŊĐ°Ņ”Ņ‚Đĩ ви, Ņ‰Đž... \ ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐŋŅ€Đ¸ СаĐŋ҃ҁĐē҃ \ ĐĐ°ŅŅ‚ŅƒĐŋĐŊа \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_vi.h000066400000000000000000000063761516402577000240120ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_VI #define H_OBJSMOOTH_I18N_VI static const char *smooth_vi = " \ \ \ smooth \ Vietnamese / Tiáēŋng Viáģ‡t \ false \ UTF-8 \ \ \ Đáģ“ng ÃŊ \ Háģ§y báģ \ CÃŗ \ Không \ Tháģ­ láēĄi \ Báģ qua \ Báģ \ \ Háģ“i láēĄi \ Cáē¯t \ ChÊp \ DÃĄn \ XoÃĄ \ Cháģn háēŋt \ \ XoÃĄ lÚi \ TáēĄo báēŖng \ Nháē­p \ ThoÃĄt \ Phím dài \ LÃĒn trang \ Xuáģ‘ng trang \ Cuáģ‘i \ Váģ \ TrÃĄi \ LÃĒn \ PháēŖi \ Xuáģ‘ng \ Chèn \ XoÃĄ báģ \ Điáģu khiáģƒn \ Xen káēŊ \ Dáģ‹ch \ \ MáģŸ file \ Lưu file \ Lưu file dưáģ›i dáēĄng ... \ Cháģn thư máģĨc \ Cháģn kiáģƒu cháģ¯ \ \ Cháģn màu \ MÃŖ HTML \ \ Tháģ§ thuáē­t cho báēĄn \ BáēĄn cÃŗ biáēŋt ... \ Hiáģƒn tháģ‹ khi cháēĄy \ Tiáēŋp theo \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_zh_CN.h000066400000000000000000000046551516402577000243730ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_ZH_CN #define H_OBJSMOOTH_I18N_ZH_CN static const char *smooth_zh_CN = " \ \ \ smooth \ Chinese (simplified) / įŽ€äŊ“中文 \ false \ UTF-8 \ \ \ įĄŽčŽ¤ \ 取æļˆ \ 是 \ åĻ \ é‡č¯• \ 退å‡ē \ åŋŊį•Ĩ \ \ 撤æļˆ \ å‰Ē切 \ 复åˆļ \ ម贴 \ 清除 \ 全部选中 \ \ įŠēæ ŧ \ \ 打åŧ€æ–‡äģļ \ äŋå­˜æ–‡äģļ \ 文äģļåĻ存ä¸ē ... \ é€‰æ‹Šį›ŽåŊ• \ 选拊字äŊ“ \ \ 选拊éĸœč‰˛ \ HTML äģŖį  \ \ ä슿—Ĩ提į¤ē \ äŊ įŸĨ道吗 ... \ 启动æ—ļ昞į¤ē提į¤ē \ ä¸‹ä¸€æĄ \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_zh_HK.h000066400000000000000000000045361516402577000243730ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_ZH_HK #define H_OBJSMOOTH_I18N_ZH_HK static const char *smooth_zh_HK = " \ \ \ smooth \ Cantonese (Hong Kong) / éĻ™æ¸¯æ­Ŗé̔字 \ false \ UTF-8 \ \ \ įĸē厚 \ 取æļˆ \ 是 \ åĻ \ 重čŠĻ \ įĩ‚æ­ĸ \ åŋŊį•Ĩ \ \ 垊原 \ å‰Ē下 \ 複čŖŊ \ č˛ŧ上 \ 清除 \ 全選 \ \ 開啟æĒ”æĄˆ \ å„˛å­˜æĒ”æĄˆ \ åĻ存新æĒ” \ é¸æ“‡čˇ¯åž‘ \ 選擇字型 \ \ é¸æ“‡č‰˛åŊŠ \ HTMLäģŖįĸŧ \ \ 每æ—Ĩ提į¤ē \ 提į¤ē \ å•Ÿå‹•æ™‚éĄ¯į¤ēæœŦ提į¤ē \ 下一個 \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/locales/smooth_zh_TW.h000066400000000000000000000045461516402577000244240ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef H_OBJSMOOTH_I18N_ZH_TW #define H_OBJSMOOTH_I18N_ZH_TW static const char *smooth_zh_TW = " \ \ \ smooth \ Chinese (traditional) / įšéĢ”ä¸­æ–‡ \ false \ UTF-8 \ \ \ įĸē厚 \ 取æļˆ \ 是 \ åĻ \ 重čŠĻ \ 中æ­ĸ \ åŋŊį•Ĩ \ \ 垊原 \ å‰Ē下 \ 複čŖŊ \ č˛ŧ上 \ 清除 \ 全選 \ \ 開啟æĒ”æĄˆ \ å„˛å­˜æĒ”æĄˆ \ åĻ存新æĒ” \ é¸æ“‡į›ŽéŒ„ \ 選擇字型 \ \ é¸æ“‡éĄč‰˛ \ HTMLäģŖįĸŧ \ \ 每æ—Ĩ小įĨ•荪 \ 您įŸĨ道嗎... \ å•Ÿå‹•æ™‚éĄ¯į¤ēå°į§˜č¨Ŗ \ 下一頁 \ \ "; #endif smooth-0.9.11~git20260403.0230c0da/classes/i18n/number.cpp000077500000000000000000000041111516402577000221700ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #ifdef __WIN32__ # include #endif S::String S::I18n::Number::GetLocalizedNumberString(Int64 number) { /* Localize a number according to the current locale settings */ Int negFormat = 1; String sThousand = "."; String sGrouping = "3;0"; #ifdef __WIN32__ wchar_t buffer[10]; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_INEGNUMBER, buffer, 2); negFormat = String(buffer).ToInt(); GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, buffer, 4); sThousand = buffer; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, buffer, 10); sGrouping = buffer; #endif String nString = String::FromInt(number >= 0 ? number : -number); String retVal; /* Separate number blocks. */ const Array &groupSize = sGrouping.Explode(";"); Int group = 0; Int count = 0; for (Int i = nString.Length() - 1; i >= 0; i--) { if (groupSize.Length() > group && groupSize.GetNth(group).ToInt() == count++) { retVal = String(sThousand).Append(retVal); count = 1; group++; if (groupSize.Length() > group && groupSize.GetNth(group).ToInt() == 0) group--; } retVal = String().FillN(nString[i], 1).Append(retVal); } /* Format negative numbers according to the locale. */ if (number < 0) { switch (negFormat) { case 0: // (1.1) retVal = String("(").Append(retVal).Append(")"); break; case 1: // -1.1 retVal = String("-").Append(retVal); break; case 2: // - 1.1 retVal = String("- ").Append(retVal); break; case 3: // 1.1- retVal.Append("-"); break; case 4: // 1.1 - retVal.Append(" -"); break; } } return retVal; } smooth-0.9.11~git20260403.0230c0da/classes/i18n/section.cpp000066400000000000000000000046051516402577000223510ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::I18n::Section::Section() { contextSection = NIL; } S::I18n::Section::~Section() { foreach (Section *section, sections) delete section; } const S::String &S::I18n::Section::GetString(const String &string) const { if (contextSection != NIL) { const String &result = contextSection->GetString(string); if (result != NIL) return result; } return strings.Get(string.ComputeCRC32()); } S::Bool S::I18n::Section::SetContext(const String &nContext) { context = nContext; contextSection = NIL; if (context != NIL) { Int index = context.Find("::"); String contextFirst = context; String contextRest; if (index >= 0) { contextFirst = context.Head(index); contextRest = context.Tail(context.Length() - index - 2); } foreach (Section *section, sections) { if (section->GetName() == contextFirst) { section->SetContext(contextRest); contextSection = section; return True; } } return False; } return True; } S::Errors::Error S::I18n::Section::Parse(XML::Node *section) { if (section == NIL) return Error(); static String sectionNode = "section"; static String nameAttribute = "name"; static String entryNode = "entry"; static String stringAttribute = "string"; if (section->GetAttributeByName(nameAttribute) != NIL) SetName(section->GetAttributeByName(nameAttribute)->GetContent()); for (Int i = 0; i < section->GetNOfNodes(); i++) { XML::Node *entry = section->GetNthNode(i); if (entry->GetName() == entryNode && entry->GetAttributeByName(stringAttribute) != NIL) { strings.Add(entry->GetContent(), entry->GetAttributeByName(stringAttribute)->GetContent().ComputeCRC32()); } else if (entry->GetName() == sectionNode && entry->GetAttributeByName(nameAttribute) != NIL) { Section *section = new Section(); section->Parse(entry); sections.Add(section, section->GetName().ComputeCRC32()); } } return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/i18n/translator.cpp000077500000000000000000000534621516402577000231060ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #ifdef __WIN32__ # include #else # include # include # include #endif namespace smooth { static String GetApplicationName() { String appName; for (Int i = 0; i < Object::GetNOfObjects(); i++) { if (Object::GetNthObject(i)->GetObjectType() != GUI::Application::classID) continue; GUI::Application *application = (GUI::Application *) Object::GetNthObject(i); appName = application->GetText(); appName.Replace(":", NIL).Replace("/", NIL); break; } return appName; } static Array GetTranslationFolders(const String &appPrefix) { Array dirs; /* Add application data folders. */ String appName = GetApplicationName(); dirs.Add(S::System::System::GetApplicationDataDirectory().Append(appPrefix).Append(Directory::GetDirectoryDelimiter()).Append("lang")); if (appName != NIL && appName != appPrefix) dirs.Add(S::System::System::GetApplicationDataDirectory().Append(appName).Append(Directory::GetDirectoryDelimiter()).Append("lang")); /* Add application folder. */ dirs.Add(GUI::Application::GetApplicationDirectory().Append("lang")); #ifndef __WIN32__ /* Add resources folders. */ dirs.Add(S::System::System::GetResourcesDirectory().Append(appPrefix).Append(Directory::GetDirectoryDelimiter()).Append("lang")); if (appName != NIL && appName != appPrefix) dirs.Add(S::System::System::GetResourcesDirectory().Append(appName).Append(Directory::GetDirectoryDelimiter()).Append("lang")); #endif return dirs; } } S::I18n::Translator *S::I18n::Translator::defaultTranslator = NIL; S::I18n::Translator::Translator(const String &iAppPrefix) { appPrefix = iAppPrefix.ToLower(); activeLanguage = NIL; GetSupportedLanguages(); ActivateLanguage("internal"); } S::I18n::Translator::~Translator() { foreach (Language *language, languages) delete language; languages.RemoveAll(); } S::Int S::I18n::Translator::SetInternalLanguageInfo(const String &langName, const String &author, const String &url, Bool rightToLeft) { Language *iLang = NIL; for (Int n = 0; n < languages.Length(); n++) { if (languages.GetNth(n)->magic == "internal") { iLang = languages.GetNth(n); languages.Remove(languages.GetNthIndex(n)); break; } } if (iLang != NIL) { iLang->SetName(langName); iLang->author = author; iLang->url = url; iLang->rightToLeft = rightToLeft; AddLanguage(iLang); } return Success(); } S::String S::I18n::Translator::GetUserDefaultLanguageCode() { String code; #if defined __WIN32__ LANGID langid = GetUserDefaultLangID(); switch (PRIMARYLANGID(langid)) { case LANG_ENGLISH: code = "en"; if (SUBLANGID(langid) == SUBLANG_ENGLISH_AUS) code = "en_AU"; else if (SUBLANGID(langid) == SUBLANG_ENGLISH_CAN) code = "en_CA"; else if (SUBLANGID(langid) == SUBLANG_ENGLISH_NZ) code = "en_NZ"; else if (SUBLANGID(langid) == SUBLANG_ENGLISH_US) code = "en_US"; else if (SUBLANGID(langid) == SUBLANG_ENGLISH_UK) code = "en_UK"; break; case LANG_AFRIKAANS: code = "af"; break; case LANG_ALBANIAN: code = "sq"; break; case LANG_AMHARIC: code = "am"; break; case LANG_ARABIC: code = "ar"; if (SUBLANGID(langid) == SUBLANG_ARABIC_ALGERIA) code = "ar_DZ"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_BAHRAIN) code = "ar_BH"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_EGYPT) code = "ar_EG"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_IRAQ) code = "ar_IQ"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_JORDAN) code = "ar_JO"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_KUWAIT) code = "ar_KW"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_LEBANON) code = "ar_LB"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_LIBYA) code = "ar_LY"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_MOROCCO) code = "ar_MO"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_OMAN) code = "ar_OM"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_QATAR) code = "ar_QA"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_SAUDI_ARABIA) code = "ar_SA"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_SYRIA) code = "ar_SY"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_TUNISIA) code = "ar_TN"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_UAE) code = "ar_AE"; else if (SUBLANGID(langid) == SUBLANG_ARABIC_YEMEN) code = "ar_YE"; break; case LANG_ARMENIAN: code = "hy"; break; case LANG_ASSAMESE: code = "as"; break; case LANG_AZERI: code = "az"; if (SUBLANGID(langid) == SUBLANG_AZERI_LATIN) code = "az_AZ@Latn"; else if (SUBLANGID(langid) == SUBLANG_AZERI_CYRILLIC) code = "az_AZ@Cyrl"; break; case LANG_BANGLA: code = "bn"; if (SUBLANGID(langid) == SUBLANG_BANGLA_BANGLADESH) code = "bn_BD"; else if (SUBLANGID(langid) == SUBLANG_BANGLA_INDIA) code = "bn_IN"; break; case LANG_BASQUE: code = "eu"; break; case LANG_BELARUSIAN: code = "be"; break; case LANG_BRETON: code = "br"; break; case LANG_BULGARIAN: code = "bg"; break; case LANG_CATALAN: code = "ca"; break; case LANG_CHINESE: code = "zh_TW"; if (SUBLANGID(langid) == SUBLANG_CHINESE_SIMPLIFIED) code = "zh_CN"; else if (SUBLANGID(langid) == SUBLANG_CHINESE_TRADITIONAL) code = "zh_TW"; else if (SUBLANGID(langid) == SUBLANG_CHINESE_HONGKONG) code = "zh_HK"; else if (SUBLANGID(langid) == SUBLANG_CHINESE_MACAU) code = "zh_MO"; else if (SUBLANGID(langid) == SUBLANG_CHINESE_SINGAPORE) code = "zh_SG"; break; case LANG_CORSICAN: code = "co"; break; case LANG_CZECH: code = "cs"; break; case LANG_DANISH: code = "da"; break; case LANG_DARI: code = "prs"; break; case LANG_DIVEHI: code = "dv"; break; case LANG_DUTCH: code = "nl"; if (SUBLANGID(langid) == SUBLANG_DUTCH) code = "nl_NL"; else if (SUBLANGID(langid) == SUBLANG_DUTCH_BELGIAN) code = "nl_BE"; break; case LANG_ESTONIAN: code = "et"; break; case LANG_FILIPINO: code = "fil"; break; case LANG_FINNISH: code = "fi"; break; case LANG_FRENCH: code = "fr"; if (SUBLANGID(langid) == SUBLANG_FRENCH) code = "fr_FR"; else if (SUBLANGID(langid) == SUBLANG_FRENCH_BELGIAN) code = "fr_BE"; else if (SUBLANGID(langid) == SUBLANG_FRENCH_CANADIAN) code = "fr_CA"; else if (SUBLANGID(langid) == SUBLANG_FRENCH_LUXEMBOURG) code = "fr_LU"; else if (SUBLANGID(langid) == SUBLANG_FRENCH_MONACO) code = "fr_MC"; else if (SUBLANGID(langid) == SUBLANG_FRENCH_SWISS) code = "fr_CH"; break; case LANG_GALICIAN: code = "gl"; break; case LANG_GEORGIAN: code = "ka"; break; case LANG_GERMAN: code = "de"; break; case LANG_GREEK: code = "el"; break; case LANG_GUJARATI: code = "gu"; break; case LANG_HAUSA: code = "ha"; break; case LANG_HEBREW: code = "he"; break; case LANG_HINDI: code = "hi"; break; case LANG_HUNGARIAN: code = "hu"; break; case LANG_ICELANDIC: code = "is"; break; case LANG_IGBO: code = "ig"; break; case LANG_INDONESIAN: code = "id"; break; case LANG_IRISH: code = "ga"; break; case LANG_ITALIAN: code = "it"; break; case LANG_JAPANESE: code = "ja"; break; case LANG_KANNADA: code = "kn"; break; case LANG_KAZAK: code = "kk"; break; case LANG_KHMER: code = "kh"; break; case LANG_KINYARWANDA: code = "rw"; break; case LANG_KOREAN: code = "ko"; break; case LANG_KYRGYZ: code = "ky"; break; case LANG_LAO: code = "lo"; break; case LANG_LATVIAN: code = "lv"; break; case LANG_LITHUANIAN: code = "lt"; break; case LANG_LUXEMBOURGISH:code = "lb"; break; case LANG_MACEDONIAN: code = "mk"; break; case LANG_MALAY: code = "ms"; break; case LANG_MALAYALAM: code = "ml"; break; case LANG_MALTESE: code = "mt"; break; case LANG_MAORI: code = "mi"; break; case LANG_MARATHI: code = "mr"; break; case LANG_MONGOLIAN: code = "mn"; break; case LANG_NEPALI: code = "ni"; break; case LANG_NORWEGIAN: code = "no"; break; case LANG_OCCITAN: code = "oc"; break; case LANG_ORIYA: code = "or"; break; case LANG_PASHTO: code = "ps"; break; case LANG_PERSIAN: code = "fa"; break; case LANG_POLISH: code = "pl"; break; case LANG_PORTUGUESE: code = "pt"; if (SUBLANGID(langid) == SUBLANG_PORTUGUESE) code = "pt_PT"; else if (SUBLANGID(langid) == SUBLANG_PORTUGUESE_BRAZILIAN) code = "pt_BR"; break; case LANG_PULAR: code = "ff"; break; case LANG_PUNJABI: code = "pa"; if (SUBLANGID(langid) == SUBLANG_PUNJABI_INDIA) code = "pa_IN"; else if (SUBLANGID(langid) == SUBLANG_PUNJABI_PAKISTAN) code = "pa_PK"; break; case LANG_QUECHUA: code = "quz"; break; case LANG_ROMANIAN: code = "ro"; break; case LANG_RUSSIAN: code = "ru"; break; case LANG_SERBIAN: code = "sr"; if (SUBLANGID(langid) == SUBLANG_CROATIAN_CROATIA) code = "hr_HR"; else if (SUBLANGID(langid) == SUBLANG_SERBIAN_LATIN) code = "sr_RS@Latn"; else if (SUBLANGID(langid) == SUBLANG_SERBIAN_CYRILLIC) code = "sr_RS@Cyrl"; break; case LANG_SINHALESE: code = "si"; break; case LANG_SLOVAK: code = "sk"; break; case LANG_SLOVENIAN: code = "sl"; break; case LANG_SOTHO: code = "sa"; break; case LANG_SPANISH: code = "es"; if (SUBLANGID(langid) == SUBLANG_SPANISH) code = "es_ES"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_ARGENTINA) code = "es_AR"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_BOLIVIA) code = "es_BO"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_CHILE) code = "es_CL"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_COLOMBIA) code = "es_CO"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_COSTA_RICA) code = "es_CR"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_DOMINICAN_REPUBLIC) code = "es_DO"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_ECUADOR) code = "es_EC"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_EL_SALVADOR) code = "es_SV"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_GUATEMALA) code = "es_GT"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_HONDURAS) code = "es_HN"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_MEXICAN) code = "es_MX"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_NICARAGUA) code = "es_NI"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_PANAMA) code = "es_PA"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_PARAGUAY) code = "es_PY"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_PERU) code = "es_PE"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_PUERTO_RICO) code = "es_PR"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_URUGUAY) code = "es_UY"; else if (SUBLANGID(langid) == SUBLANG_SPANISH_VENEZUELA) code = "es_VE"; break; case LANG_SWAHILI: code = "sw"; break; case LANG_SWEDISH: code = "sv"; break; case LANG_TAJIK: code = "tg"; break; case LANG_TAMIL: code = "ta"; if (SUBLANGID(langid) == SUBLANG_TAMIL_INDIA) code = "ta_IN"; else if (SUBLANGID(langid) == SUBLANG_TAMIL_SRI_LANKA) code = "ta_LK"; break; case LANG_TELUGU: code = "te"; break; case LANG_THAI: code = "th"; break; case LANG_TIBETAN: code = "bo"; break; case LANG_TIGRINYA: code = "ti"; break; case LANG_TSWANA: code = "tn"; break; case LANG_TURKISH: code = "tr"; break; case LANG_TURKMEN: code = "tk"; break; case LANG_UIGHUR: code = "ug"; break; case LANG_UKRAINIAN: code = "uk"; break; case LANG_URDU: code = "ur"; if (SUBLANGID(langid) == SUBLANG_URDU_INDIA) code = "ur_IN"; else if (SUBLANGID(langid) == SUBLANG_URDU_PAKISTAN) code = "ur_PK"; break; case LANG_UZBEK: code = "uz"; if (SUBLANGID(langid) == SUBLANG_UZBEK_LATIN) code = "uz_UZ@Latn"; else if (SUBLANGID(langid) == SUBLANG_UZBEK_CYRILLIC) code = "uz_UZ@Cyrl"; break; case LANG_VIETNAMESE: code = "vi"; break; case LANG_WELSH: code = "cy"; break; case LANG_WOLOF: code = "wo"; break; case LANG_XHOSA: code = "xh"; break; case LANG_YI: code = "ii"; break; case LANG_YORUBA: code = "yo"; break; case LANG_ZULU: code = "zu"; break; } #elif defined __APPLE__ FILE *pstdin = popen("defaults read -g AppleLocale", "r"); Buffer buffer(256); buffer.Zero(); fscanf(pstdin, String("%[^\n]").Append(String::FromInt(buffer.Size() - 1)), (char *) buffer); pclose(pstdin); code = (char *) buffer; #elif defined __HAIKU__ FILE *pstdin = popen("locale -l", "r"); Buffer buffer(256); buffer.Zero(); fscanf(pstdin, String("%[^\n]").Append(String::FromInt(buffer.Size() - 1)), (char *) buffer); pclose(pstdin); code = (char *) buffer; #else code = getenv("LANG"); if (code == NIL) code = getenv("LC_MESSAGES"); #endif if (code.Contains(".")) code = code.Head(code.Find(".")).Append(code.Contains("@") ? code.Tail(code.Length() - code.Find("@")) : ""); code.Replace("@latin", "@Latn"); code.Replace("@cyrillic", "@Cyrl"); return code; } S::Int S::I18n::Translator::SelectUserDefaultLanguage() { String code = GetUserDefaultLanguageCode(); /* Try the language code, possibly with appended country and script code. */ if (ActivateLanguage(String(appPrefix).Append("_").Append(code).Append(".xml")) == Success()) return Success(); /* If failed, try without the script code if applicable. */ if (code.Contains("@")) { if (ActivateLanguage(String(appPrefix).Append("_").Append(code.Head(code.Find("@"))).Append(".xml")) == Success()) return Success(); } /* If failed, try without the country code if applicable. */ if (code.Contains("_") && code.Contains("@")) { if (ActivateLanguage(String(appPrefix).Append("_").Append(code.Head(code.Find("_"))).Append(code.Contains("@") ? code.Tail(code.Length() - code.Find("@")) : "").Append(".xml")) == Success()) return Success(); } /* If failed, try the base language code if applicable. */ if (code.Contains("_")) { if (ActivateLanguage(String(appPrefix).Append("_").Append(code.Head(code.Find("_"))).Append(".xml")) == Success()) return Success(); } /* Fall back to alternative language. */ if (code.StartsWith("fil") && ActivateLanguage(String(appPrefix).Append("_tl.xml")) == Success()) return Success(); // Fall back to Tagalog for Filipino else if (code.StartsWith("prs") && ActivateLanguage(String(appPrefix).Append("_fa.xml")) == Success()) return Success(); // Fall back to Persian for Dari else if (code.StartsWith("zh_MO") && ActivateLanguage(String(appPrefix).Append("_zh_HK.xml")) == Success()) return Success(); // Fall back to Cantonese (Hong Kong) for Cantonese (Macau) /* Fall back to internal language. */ ActivateLanguage("internal"); return Success(); } S::Int S::I18n::Translator::GetSupportedLanguages() { /* Add default translation. */ { Language *language = new Language(); language->SetName("Default language"); language->encoding = "UTF-8"; language->magic = "internal"; language->author = "unknown"; language->url = "none"; language->rightToLeft = False; languages.Add(language); } /* Check translation folders. */ const Array &dirs = GetTranslationFolders(appPrefix); foreach (const Directory &dir, dirs) { if (!dir.Exists() || dir.GetFilesByPattern(String(appPrefix).Append("_*.xml")).Length() == 0) continue; /* Load translation files. */ const Array &files = dir.GetFilesByPattern(String(appPrefix).Append("_*.xml")); foreach (const File &file, files) { XML::Document doc; if (doc.LoadFile(file) == Success()) { Language *language = new Language(); language->magic = file.GetFileName(); if (LoadDescription(doc, language) == Success()) AddLanguage(language); } } } return Success(); } S::Bool S::I18n::Translator::SetContext(const String &nContext) { return activeLanguage->SetContext(nContext); } const S::String &S::I18n::Translator::GetContext() const { return activeLanguage->GetContext(); } S::Int S::I18n::Translator::GetNOfLanguages() const { return languages.Length(); } const S::String &S::I18n::Translator::GetNthLanguageName(Int index) const { return languages.GetNth(index)->GetName(); } const S::String &S::I18n::Translator::GetNthLanguageID(Int index) const { return languages.GetNth(index)->magic; } const S::String &S::I18n::Translator::GetNthLanguageAuthor(Int index) const { return languages.GetNth(index)->author; } const S::String &S::I18n::Translator::GetNthLanguageEncoding(Int index) const { return languages.GetNth(index)->encoding; } const S::String &S::I18n::Translator::GetNthLanguageURL(Int index) const { return languages.GetNth(index)->url; } S::Bool S::I18n::Translator::IsNthLanguageRightToLeft(Int index) const { return languages.GetNth(index)->rightToLeft; } S::Bool S::I18n::Translator::IsNthLanguageIncomplete(Int index) const { return languages.GetNth(index)->incomplete; } const S::String &S::I18n::Translator::GetActiveLanguageName() const { return activeLanguage->GetName(); } const S::String &S::I18n::Translator::GetActiveLanguageID() const { return activeLanguage->magic; } const S::String &S::I18n::Translator::GetActiveLanguageAuthor() const { return activeLanguage->author; } const S::String &S::I18n::Translator::GetActiveLanguageEncoding() const { return activeLanguage->encoding; } const S::String &S::I18n::Translator::GetActiveLanguageURL() const { return activeLanguage->url; } S::Bool S::I18n::Translator::IsActiveLanguageRightToLeft() const { return activeLanguage->rightToLeft; } S::Bool S::I18n::Translator::IsActiveLanguageIncomplete() const { return activeLanguage->incomplete; } S::Int S::I18n::Translator::ActivateLanguage(const String &magic) { foreach (Language *language, languages) { if (language->magic != magic) continue; activeLanguage = language; /* Try to set application language for internal library strings. */ if (magic != "internal") { String code = magic.SubString(magic.Find("_") + 1, magic.Find(".xml") - magic.Find("_") - 1); String id = String("smooth_").Append(code).Append(".xml"); if (defaultTranslator->ActivateLanguage(id) != Success()) { /* If failed, try the base language code if applicable. */ if (code.Contains("_")) { id = String("smooth_").Append(code.Head(code.Find("_"))).Append(".xml"); defaultTranslator->ActivateLanguage(id); } } /* Activate user default language if setting the application language failed. */ if (defaultTranslator->GetActiveLanguageID() != id) defaultTranslator->SelectUserDefaultLanguage(); } /* Activate internal language if application language is set to internal. */ if (magic == "internal" && defaultTranslator != NIL) defaultTranslator->ActivateLanguage(magic); /* Load actual language data. */ if (magic != "internal" && activeLanguage->strings.Length() == 0 && activeLanguage->sections.Length() == 0) { /* Check translation folders. */ const Array &dirs = GetTranslationFolders(appPrefix); foreach (const Directory &dir, dirs) { /* Load translation file. */ String file = String(dir).Append(Directory::GetDirectoryDelimiter()).Append(magic); XML::Document doc; if (doc.LoadFile(file) == Success() && LoadData(doc, activeLanguage) == Success()) break; } } return Success(); } return Error(); } const S::String &S::I18n::Translator::TranslateString(const String &string) { const String &translation = activeLanguage->GetString(string); if (translation == NIL) return string; else return translation; } const S::String &S::I18n::Translator::TranslateString(const String &string, const String &context) { String prevContext = activeLanguage->GetContext(); activeLanguage->SetContext(context); const String &translation = activeLanguage->GetString(string); activeLanguage->SetContext(prevContext); if (translation == NIL) return string; else return translation; } S::Int S::I18n::Translator::AddLanguage(Language *language) { /* Check arguments and return an error if they are not sane. */ if (language == NIL) return Error(); const String &langName = language->GetName(); for (Int i = 0; i < languages.Length(); i++) { const String &compName = languages.GetNth(i)->GetName(); for (Int j = 0; j < Math::Max(langName.Length(), compName.Length()); j++) { if (langName == compName) return Error(); if ((langName[j] < compName[j] && !(langName[j] == '(' && compName[j] == '/')) || (langName[j] == '/' && compName[j] == '(')) { languages.InsertAtPos(i, language); return Success(); } if ((langName[j] > compName[j] && !(langName[j] == '/' && compName[j] == '(')) || (langName[j] == '(' && compName[j] == '/')) break; } } languages.Add(language); return Success(); } S::Int S::I18n::Translator::LoadDescription(const XML::Document &doc, Language *language) { /* Check arguments and return an error if they are not sane. */ if (doc.GetRootNode() == NIL || language == NIL) return Error(); XML::Node *root = doc.GetRootNode(); Error result = language->ParseHeader(root); if (result != Success()) return Error(); return Success(); } S::Int S::I18n::Translator::LoadData(const XML::Document &doc, Language *language) { /* Check arguments and return an error if they are not sane. */ if (doc.GetRootNode() == NIL || language == NIL) return Error(); XML::Node *root = doc.GetRootNode(); Error result = language->Parse(root); if (result != Success()) return Error(); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/i18n/translator_internal.cpp000066400000000000000000000116301516402577000247660ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2017 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include "locales/smooth_af.h" #include "locales/smooth_ar.h" #include "locales/smooth_bg.h" #include "locales/smooth_ca.h" #include "locales/smooth_ca@valencia.h" #include "locales/smooth_co.h" #include "locales/smooth_cs.h" #include "locales/smooth_da.h" #include "locales/smooth_de.h" #include "locales/smooth_el.h" #include "locales/smooth_eo.h" #include "locales/smooth_es.h" #include "locales/smooth_et.h" #include "locales/smooth_eu.h" #include "locales/smooth_fa.h" #include "locales/smooth_fi.h" #include "locales/smooth_fr.h" #include "locales/smooth_gl.h" #include "locales/smooth_he.h" #include "locales/smooth_hi.h" #include "locales/smooth_hr.h" #include "locales/smooth_hu.h" #include "locales/smooth_id.h" #include "locales/smooth_it.h" #include "locales/smooth_ja.h" #include "locales/smooth_ko.h" #include "locales/smooth_lt.h" #include "locales/smooth_lv.h" #include "locales/smooth_ms.h" #include "locales/smooth_nl.h" #include "locales/smooth_no.h" #include "locales/smooth_pa.h" #include "locales/smooth_pl.h" #include "locales/smooth_pt.h" #include "locales/smooth_pt_BR.h" #include "locales/smooth_ro.h" #include "locales/smooth_ru.h" #include "locales/smooth_sk.h" #include "locales/smooth_sl.h" #include "locales/smooth_sr.h" #include "locales/smooth_sr@Cyrl.h" #include "locales/smooth_sv.h" #include "locales/smooth_th.h" #include "locales/smooth_tr.h" #include "locales/smooth_uk.h" #include "locales/smooth_vi.h" #include "locales/smooth_zh_CN.h" #include "locales/smooth_zh_HK.h" #include "locales/smooth_zh_TW.h" namespace smooth { namespace I18n { static const char *languageXMLs[] = { smooth_af, smooth_ar, smooth_bg, smooth_ca, smooth_ca_valencia, smooth_co, smooth_cs, smooth_da, smooth_de, smooth_el, smooth_eo, smooth_es, smooth_et, smooth_eu, smooth_fa, smooth_fi, smooth_fr, smooth_gl, smooth_he, smooth_hi, smooth_hr, smooth_hu, smooth_id, smooth_it, smooth_ja, smooth_ko, smooth_lt, smooth_lv, smooth_ms, smooth_nl, smooth_no, smooth_pa, smooth_pl, smooth_pt, smooth_pt_BR, smooth_ro, smooth_ru, smooth_sk, smooth_sl, smooth_sr, smooth_sr_cyrl, smooth_sv, smooth_th, smooth_tr, smooth_uk, smooth_vi, smooth_zh_CN, smooth_zh_HK, smooth_zh_TW, NIL }; static const char *languageMagics[] = { "smooth_af.xml", "smooth_ar.xml", "smooth_bg.xml", "smooth_ca.xml", "smooth_ca@valencia.xml", "smooth_co.xml", "smooth_cs.xml", "smooth_da.xml", "smooth_de.xml", "smooth_el.xml", "smooth_eo.xml", "smooth_es.xml", "smooth_et.xml", "smooth_eu.xml", "smooth_fa.xml", "smooth_fi.xml", "smooth_fr.xml", "smooth_gl.xml", "smooth_he.xml", "smooth_hi.xml", "smooth_hr.xml", "smooth_hu.xml", "smooth_id.xml", "smooth_it.xml", "smooth_ja.xml", "smooth_ko.xml", "smooth_lt.xml", "smooth_lv.xml", "smooth_ms.xml", "smooth_nl.xml", "smooth_no.xml", "smooth_pa.xml", "smooth_pl.xml", "smooth_pt.xml", "smooth_pt_BR.xml", "smooth_ro.xml", "smooth_ru.xml", "smooth_sk.xml", "smooth_sl.xml", "smooth_sr.xml", "smooth_sr@Cyrl.xml", "smooth_sv.xml", "smooth_th.xml", "smooth_tr.xml", "smooth_uk.xml", "smooth_vi.xml", "smooth_zh_CN.xml", "smooth_zh_HK.xml", "smooth_zh_TW.xml", NIL }; }; }; S::I18n::TranslatorInternal::TranslatorInternal() : Translator("smooth") { GetSupportedLanguages(); } S::I18n::TranslatorInternal::~TranslatorInternal() { } S::Int S::I18n::TranslatorInternal::GetSupportedLanguages() { SetInternalLanguageInfo("English", "Robert Kausch", "http://www.smooth-project.org/", False); for (Int i = 0; languageXMLs[i] != NIL; i++) { const char *xml = languageXMLs[i]; XML::Document doc; if (doc.ParseMemory((void *) xml, strlen(xml)) == Success()) { Language *language = new Language(); language->magic = languageMagics[i]; if (LoadDescription(doc, language) == Success()) AddLanguage(language); } } return Success(); } S::Int S::I18n::TranslatorInternal::ActivateLanguage(const String &magic) { foreach (Language *language, languages) { if (language->magic != magic) continue; activeLanguage = language; /* Load actual language data. */ if (magic != "internal" && activeLanguage->strings.Length() == 0 && activeLanguage->sections.Length() == 0) { for (Int i = 0; languageMagics[i] != NIL; i++) { if (magic != languageMagics[i]) continue; XML::Document doc; if (doc.ParseMemory((void *) languageXMLs[i], strlen(languageXMLs[i])) == Success()) LoadData(doc, activeLanguage); } } return Success(); } return Error(); } smooth-0.9.11~git20260403.0230c0da/classes/input/000077500000000000000000000000001516402577000205545ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/input/Makefile000066400000000000000000000013021516402577000222100ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags x11) endif endif endif # Enter object files here: OBJECTS = keyboard.o pointer.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,backends) CLEANCMD1 = $(call cleanin,backends) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/input/backends/000077500000000000000000000000001516402577000223265ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/input/backends/Makefile000066400000000000000000000011171516402577000237660ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = pointerbackend.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,cocoa) && $(call makein,haiku) ALLCMD2 = $(call makein,win32) && $(call makein,xlib) CLEANCMD1 = $(call cleanin,cocoa) && $(call cleanin,haiku) CLEANCMD2 = $(call cleanin,win32) && $(call cleanin,xlib) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/input/backends/cocoa/000077500000000000000000000000001516402577000234125ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/input/backends/cocoa/Makefile000066400000000000000000000006521516402577000250550ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_OSX),True) OBJECTS += pointercocoa.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/input/backends/cocoa/pointercocoa.mm000066400000000000000000000025161516402577000264360ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Input::PointerBackend *CreatePointerCocoa() { return new S::Input::PointerCocoa(); } S::Int pointerCocoaTmp = S::Input::PointerBackend::SetBackend(&CreatePointerCocoa); S::Input::PointerCocoa::PointerCocoa() { type = POINTER_COCOA; } S::Input::PointerCocoa::~PointerCocoa() { } S::Bool S::Input::PointerCocoa::SetCursor(const GUI::Window *window, Pointer::CursorType mouseCursor) { if (mouseCursor == Pointer::CursorArrow) [[NSCursor arrowCursor] set]; else if (mouseCursor == Pointer::CursorTextEdit) [[NSCursor IBeamCursor] set]; else if (mouseCursor == Pointer::CursorHand) [[NSCursor pointingHandCursor] set]; else if (mouseCursor == Pointer::CursorHSize) [[NSCursor resizeLeftRightCursor] set]; else if (mouseCursor == Pointer::CursorVSize) [[NSCursor resizeUpDownCursor] set]; else return False; return True; } smooth-0.9.11~git20260403.0230c0da/classes/input/backends/haiku/000077500000000000000000000000001516402577000234275ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/input/backends/haiku/Makefile000066400000000000000000000006541516402577000250740ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_HAIKU),True) OBJECTS += pointerhaiku.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/input/backends/haiku/pointerhaiku.cpp000066400000000000000000000027111516402577000266360ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::Input::PointerBackend *CreatePointerHaiku() { return new S::Input::PointerHaiku(); } S::Int pointerHaikuTmp = S::Input::PointerBackend::SetBackend(&CreatePointerHaiku); S::Input::PointerHaiku::PointerHaiku() { type = POINTER_HAIKU; } S::Input::PointerHaiku::~PointerHaiku() { } S::Bool S::Input::PointerHaiku::SetCursor(const GUI::Window *window, Pointer::CursorType mouseCursor) { BApplication *app = Backends::BackendHaiku::GetApplication(); if (mouseCursor == Pointer::CursorArrow) app->SetCursor(B_CURSOR_SYSTEM_DEFAULT); else if (mouseCursor == Pointer::CursorTextEdit) app->SetCursor(B_CURSOR_I_BEAM); else if (mouseCursor == Pointer::CursorHand) app->SetCursor(B_CURSOR_SYSTEM_DEFAULT); else if (mouseCursor == Pointer::CursorHSize) app->SetCursor(B_CURSOR_SYSTEM_DEFAULT); else if (mouseCursor == Pointer::CursorVSize) app->SetCursor(B_CURSOR_SYSTEM_DEFAULT); else return False; return True; } smooth-0.9.11~git20260403.0230c0da/classes/input/backends/pointerbackend.cpp000066400000000000000000000027351516402577000260310ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::Input::PointerBackend *CreatePointerBackend() { return new S::Input::PointerBackend(); } S::Input::PointerBackend *(*S::Input::PointerBackend::backend_creator)() = &CreatePointerBackend; S::Int S::Input::PointerBackend::SetBackend(PointerBackend *(*backend)()) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::Input::PointerBackend *S::Input::PointerBackend::CreateBackendInstance() { return backend_creator(); } S::Input::PointerBackend::PointerBackend() { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) PointerWin32(); #endif type = POINTER_NONE; } S::Input::PointerBackend::~PointerBackend() { } S::Short S::Input::PointerBackend::GetPointerType() const { return type; } S::Bool S::Input::PointerBackend::SetCursor(const GUI::Window *window, Pointer::CursorType mouseCursor) { return False; } smooth-0.9.11~git20260403.0230c0da/classes/input/backends/win32/000077500000000000000000000000001516402577000232705ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/input/backends/win32/Makefile000066400000000000000000000006541516402577000247350ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_WIN32),True) OBJECTS += pointerwin32.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/input/backends/win32/pointerwin32.cpp000066400000000000000000000043121516402577000263370ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Input::PointerBackend *CreatePointerWin32() { return new S::Input::PointerWin32(); } S::Int pointerWin32Tmp = S::Input::PointerBackend::SetBackend(&CreatePointerWin32); S::Input::PointerWin32::PointerWin32() { type = POINTER_WIN32; } S::Input::PointerWin32::~PointerWin32() { } S::Bool S::Input::PointerWin32::SetCursor(const GUI::Window *window, Pointer::CursorType mouseCursor) { static HCURSOR hCursorArrow = (HCURSOR) LoadImage(NULL, MAKEINTRESOURCE(32512), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); static HCURSOR hCursorTextEdit = (HCURSOR) LoadImage(NULL, MAKEINTRESOURCE(32513), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); static HCURSOR hCursorHand = (HCURSOR) LoadImage(NULL, MAKEINTRESOURCE(32649), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); static HCURSOR hCursorHSize = (HCURSOR) LoadImage(NULL, MAKEINTRESOURCE(32644), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); static HCURSOR hCursorVSize = (HCURSOR) LoadImage(NULL, MAKEINTRESOURCE(32645), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); if (hCursorHand == NIL) hCursorHand = hCursorArrow; if (mouseCursor != Pointer::CursorArrow) SetClassLongPtr((HWND) window->GetSystemWindow(), GCLP_HCURSOR, (LONG_PTR) NIL); else SetClassLongPtr((HWND) window->GetSystemWindow(), GCLP_HCURSOR, (LONG_PTR) hCursorArrow); if (mouseCursor == Pointer::CursorArrow) ::SetCursor(hCursorArrow); else if (mouseCursor == Pointer::CursorTextEdit) ::SetCursor(hCursorTextEdit); else if (mouseCursor == Pointer::CursorHand) ::SetCursor(hCursorHand); else if (mouseCursor == Pointer::CursorHSize) ::SetCursor(hCursorHSize); else if (mouseCursor == Pointer::CursorVSize) ::SetCursor(hCursorVSize); else return False; return True; } smooth-0.9.11~git20260403.0230c0da/classes/input/backends/xlib/000077500000000000000000000000001516402577000232645ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/input/backends/xlib/Makefile000066400000000000000000000011531516402577000247240ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags x11) endif endif endif # Enter object files here: OBJECTS = ifeq ($(BUILD_XLIB),True) OBJECTS += pointerxlib.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/input/backends/xlib/pointerxlib.cpp000066400000000000000000000036401516402577000263320ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include using namespace X11; S::Input::PointerBackend *CreatePointerXLib() { return new S::Input::PointerXLib(); } S::Int pointerXLibTmp = S::Input::PointerBackend::SetBackend(&CreatePointerXLib); S::Input::PointerXLib::PointerXLib() { type = POINTER_XLIB; display = Backends::BackendXLib::GetDisplay(); } S::Input::PointerXLib::~PointerXLib() { } S::Bool S::Input::PointerXLib::SetCursor(const GUI::Window *window, Pointer::CursorType mouseCursor) { if (display == NIL) return False; static Cursor hCursorTextEdit = XCreateFontCursor(display, XC_xterm); static Cursor hCursorHand = XCreateFontCursor(display, XC_hand2); static Cursor hCursorHSize = XCreateFontCursor(display, XC_sb_h_double_arrow); static Cursor hCursorVSize = XCreateFontCursor(display, XC_sb_v_double_arrow); if (mouseCursor == Pointer::CursorArrow) XUndefineCursor(display, (Window) window->GetSystemWindow()); else if (mouseCursor == Pointer::CursorTextEdit) XDefineCursor(display, (Window) window->GetSystemWindow(), hCursorTextEdit); else if (mouseCursor == Pointer::CursorHand) XDefineCursor(display, (Window) window->GetSystemWindow(), hCursorHand); else if (mouseCursor == Pointer::CursorHSize) XDefineCursor(display, (Window) window->GetSystemWindow(), hCursorHSize); else if (mouseCursor == Pointer::CursorVSize) XDefineCursor(display, (Window) window->GetSystemWindow(), hCursorVSize); else return False; XFlush(display); return True; } smooth-0.9.11~git20260403.0230c0da/classes/input/keyboard.cpp000066400000000000000000000071251516402577000230650ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::Array S::Input::Keyboard::keyState; S::Int addKeyboardInitTmp = S::AddInitFunction(&S::Input::Keyboard::InitKeyState); S::Int addKeyboardFreeTmp = S::AddFreeFunction(&S::Input::Keyboard::FreeKeyState); S::Input::Keyboard::Keyboard() { } S::Input::Keyboard::Keyboard(const Keyboard &) { } S::Int S::Input::Keyboard::InitKeyState() { keyState.EnableLocking(); keyState.Add(False, KeyOther); keyState.Add(False, KeyBack); keyState.Add(False, KeyTab); keyState.Add(False, KeyReturn); keyState.Add(False, KeyShift); keyState.Add(False, KeyControl); keyState.Add(False, KeyAlt); keyState.Add(False, KeyEscape); keyState.Add(False, KeySpace); keyState.Add(False, KeyPrior); keyState.Add(False, KeyNext); keyState.Add(False, KeyEnd); keyState.Add(False, KeyHome); keyState.Add(False, KeyLeft); keyState.Add(False, KeyUp); keyState.Add(False, KeyRight); keyState.Add(False, KeyDown); keyState.Add(False, KeyInsert); keyState.Add(False, KeyDelete); keyState.Add(False, Key0); keyState.Add(False, Key1); keyState.Add(False, Key2); keyState.Add(False, Key3); keyState.Add(False, Key4); keyState.Add(False, Key5); keyState.Add(False, Key6); keyState.Add(False, Key7); keyState.Add(False, Key8); keyState.Add(False, Key9); keyState.Add(False, KeyA); keyState.Add(False, KeyB); keyState.Add(False, KeyC); keyState.Add(False, KeyD); keyState.Add(False, KeyE); keyState.Add(False, KeyF); keyState.Add(False, KeyG); keyState.Add(False, KeyH); keyState.Add(False, KeyI); keyState.Add(False, KeyJ); keyState.Add(False, KeyK); keyState.Add(False, KeyL); keyState.Add(False, KeyM); keyState.Add(False, KeyN); keyState.Add(False, KeyO); keyState.Add(False, KeyP); keyState.Add(False, KeyQ); keyState.Add(False, KeyR); keyState.Add(False, KeyS); keyState.Add(False, KeyT); keyState.Add(False, KeyU); keyState.Add(False, KeyV); keyState.Add(False, KeyW); keyState.Add(False, KeyX); keyState.Add(False, KeyY); keyState.Add(False, KeyZ); keyState.Add(False, KeyCommand); keyState.Add(False, KeyF1); keyState.Add(False, KeyF2); keyState.Add(False, KeyF3); keyState.Add(False, KeyF4); keyState.Add(False, KeyF5); keyState.Add(False, KeyF6); keyState.Add(False, KeyF7); keyState.Add(False, KeyF8); keyState.Add(False, KeyF9); keyState.Add(False, KeyF10); keyState.Add(False, KeyF11); keyState.Add(False, KeyF12); keyState.Add(False, KeyF13); keyState.Add(False, KeyF14); keyState.Add(False, KeyF15); keyState.Add(False, KeyF16); keyState.Add(False, KeyF17); keyState.Add(False, KeyF18); keyState.Add(False, KeyF19); keyState.Add(False, KeyF20); keyState.Add(False, KeyF21); keyState.Add(False, KeyF22); keyState.Add(False, KeyF23); keyState.Add(False, KeyF24); return Success(); } S::Int S::Input::Keyboard::FreeKeyState() { keyState.RemoveAll(); return Success(); } S::Bool S::Input::Keyboard::GetKeyState(Key key) { return keyState.Get(key); } S::Void S::Input::Keyboard::UpdateKeyState(Key key, Bool status) { keyState.Set(key, status); } S::Void S::Input::Keyboard::ResetKeyState() { foreach (Bool &status, keyState) status = False; } smooth-0.9.11~git20260403.0230c0da/classes/input/pointer.cpp000066400000000000000000000035121516402577000227410ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::Int addPointerInitTmp = S::AddInitFunction(&S::Input::Pointer::Initialize); S::Int addPointerFreeTmp = S::AddFreeFunction(&S::Input::Pointer::Free); S::Input::PointerBackend *S::Input::Pointer::backend = NIL; const S::GUI::Window *S::Input::Pointer::pointerWindow = NIL; S::GUI::Point S::Input::Pointer::mousePosition = S::GUI::Point(); S::Input::Pointer::Pointer() { } S::Input::Pointer::Pointer(const Pointer &) { } S::Int S::Input::Pointer::Initialize() { backend = PointerBackend::CreateBackendInstance(); return Success(); } S::Int S::Input::Pointer::Free() { delete backend; return Success(); } S::Bool S::Input::Pointer::SetCursor(const GUI::Window *window, CursorType mouseCursor) { return backend->SetCursor(window, mouseCursor); } const S::GUI::Point &S::Input::Pointer::GetPosition() { return mousePosition; } const S::GUI::Window *S::Input::Pointer::GetPointerWindow() { return pointerWindow; } S::Void S::Input::Pointer::UpdatePosition(const GUI::Window *window, Int x, Int y) { pointerWindow = window; mousePosition.x = x; mousePosition.y = y; /* FixMe: The -2 offsets seem to be necessary on * all X11 systems. However, I somehow feel * this can't be the right way to do it. */ #ifndef __WIN32__ mousePosition.x -= 2; mousePosition.y -= 2; #endif } smooth-0.9.11~git20260403.0230c0da/classes/io/000077500000000000000000000000001516402577000200245ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/io/Makefile000066400000000000000000000010251516402577000214620ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. # Enter object files here: OBJECTS = driver.o filter.o instream.o outstream.o stream.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,drivers) ALLCMD2 = $(call makein,filters) CLEANCMD1 = $(call cleanin,drivers) CLEANCMD2 = $(call cleanin,filters) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/io/driver.cpp000077500000000000000000000031201516402577000220220ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::IO::Driver::Driver() { streamID = NIL; size = 2147483647; position = 0; lastError = IO_ERROR_OK; } S::IO::Driver::~Driver() { } S::Int S::IO::Driver::GetLastError() const { return lastError; } S::Int S::IO::Driver::ReadData(UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; memset((Void *) data, 0, dataSize); position += dataSize; return dataSize; } S::Int S::IO::Driver::WriteData(const UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; position += dataSize; return dataSize; } S::Int64 S::IO::Driver::Seek(Int64 newPos) { position = newPos; return position; } S::Bool S::IO::Driver::Truncate(Int64 newSize) { return False; } S::Bool S::IO::Driver::Flush() { return True; } S::Bool S::IO::Driver::Close() { return True; } S::Int64 S::IO::Driver::GetSize() const { return size; } S::Int64 S::IO::Driver::GetPos() const { return position; } S::Bool S::IO::Driver::IsBuffered() const { return False; } S::Bool S::IO::Driver::SetBufferSize(Int size) { return False; } const S::String &S::IO::Driver::GetStreamID() const { return streamID; } smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/000077500000000000000000000000001516402577000215025ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/Makefile000066400000000000000000000010421516402577000231370ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = driver_ansi.o driver_https.o driver_memory.o driver_posix.o driver_socket.o driver_socks4.o driver_socks5.o driver_zero.o ifeq ($(BUILD_WIN32),True) OBJECTS += driver_win32.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/driver_ansi.cpp000077500000000000000000000105131516402577000245160ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #if defined __WIN32__ # include # include # define fopen _wfopen # if !defined __MINGW32__ # define fseeko _fseeki64 # define ftello _ftelli64 # endif # define ftruncate chsize #else # include #endif S::IO::DriverANSI::DriverANSI(const String &file, Int mode) : Driver() { stream = NIL; closeStream = False; #if defined __WIN32__ /* Add N mode option and Unicode prefix on Windows. */ String options = "N"; String fileName = Directory::MakeExtendedPath(file); #else /* Use e mode option on other systems. */ String options = "e"; String fileName = file; /* Set output format to UTF-8 on non-Windows systems. */ String::OutputFormat outputFormat("UTF-8"); #endif switch (mode) { default: lastError = IO_ERROR_BADPARAM; return; case OS_APPEND: // open a file for appending data stream = fopen(fileName, String("r+b").Append(options)); if (stream != NIL) { Int64 size = GetSize(); if (size >= 0) Seek(size); } break; case OS_REPLACE: // create or overwrite a file stream = fopen(fileName, String("w+b").Append(options)); break; case IS_READ | IS_WRITE: // open a file for reading data stream = fopen(fileName, String("r+b").Append(options)); break; case IS_READ: // open a file in read only mode stream = fopen(fileName, String("rb").Append(options)); break; } /* Check if stream was opened successfully. */ if (stream == NIL) { if (errno == EACCES) lastError = IO_ERROR_NOACCESS; else lastError = IO_ERROR_UNEXPECTED; return; } streamID = fileName; closeStream = True; } S::IO::DriverANSI::DriverANSI(FILE *iStream) : Driver() { stream = iStream; closeStream = False; } S::IO::DriverANSI::~DriverANSI() { Close(); } S::Int S::IO::DriverANSI::ReadData(UnsignedByte *data, Int dataSize) { if (!stream || dataSize <= 0) return 0; /* Switch between read and write mode. */ if (position == -1) fseeko(stream, 0, SEEK_CUR); position = 1; /* Perform actual read operation. */ return fread(data, 1, dataSize, stream); } S::Int S::IO::DriverANSI::WriteData(const UnsignedByte *data, Int dataSize) { if (!stream || dataSize <= 0) return 0; /* Switch between read and write mode. */ if (position == 1) fseeko(stream, 0, SEEK_CUR); position = -1; /* Perform actual write operation. */ return fwrite(data, 1, dataSize, stream); } S::Int64 S::IO::DriverANSI::Seek(Int64 newPos) { if (!stream || fseeko(stream, newPos, SEEK_SET) != 0) return -1; /* Reset read/write mode indicator. */ position = 0; return GetPos(); } S::Bool S::IO::DriverANSI::Truncate(Int64 newSize) { if (!stream || fflush(stream) != 0 || ftruncate(fileno(stream), newSize) != 0) return False; return True; } S::Bool S::IO::DriverANSI::Flush() { if (!stream || fflush(stream) != 0) return False; return True; } S::Bool S::IO::DriverANSI::Close() { if (!stream || !closeStream || fclose(stream) != 0) return False; stream = NIL; closeStream = False; return True; } S::Int64 S::IO::DriverANSI::GetSize() const { if (!stream) return -1; Int64 oldPos = GetPos(); if (fseeko(stream, 0, SEEK_END) != 0) return -1; Int64 size = GetPos(); if (fseeko(stream, oldPos, SEEK_SET) != 0) return -1; return size; } S::Int64 S::IO::DriverANSI::GetPos() const { if (!stream) return -1; return ftello(stream); } S::Bool S::IO::DriverANSI::IsBuffered() const { return True; } S::Bool S::IO::DriverANSI::SetBufferSize(Int size) { if (!stream) return False; Int64 pos = GetPos(); Int mode = size > 0 ? _IOFBF : _IONBF; if (setvbuf(stream, NULL, mode, size) != 0) return False; if (Seek(pos) < 0) return False; return True; } smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/driver_https.cpp000077500000000000000000000061151516402577000247310ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #if defined __WIN32__ # include #else # include # include # include # include #endif S::IO::DriverHTTPS::DriverHTTPS(const String &proxy, Int httpPort, const String &hostName, Int port, const String &uname, const String &passwd) : Driver() { closeStream = False; stream = -1; size = -1; if (hostName.Length() > 255) { lastError = IO_ERROR_BADPARAM; return; } /* Open TCP/IP socket. */ stream = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (stream == (unsigned) (~0)) { lastError = IO_ERROR_UNEXPECTED; return; } closeStream = True; /* Get proxy hostname. */ hostent *host = gethostbyname(proxy); if (host == NIL) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Connect to proxy. */ sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_addr = *((in_addr *) *host->h_addr_list); saddr.sin_port = htons((short) httpPort); memset(&saddr.sin_zero, 0, sizeof(saddr.sin_zero)); if (connect(stream, (sockaddr *) &saddr, sizeof(struct sockaddr)) == -1) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Send connect request. */ String connect = String("CONNECT ").Append(hostName).Append(":").Append(String::FromInt(port)).Append(" HTTP/1.1\n"); if (uname != NIL) connect.Append("Proxy-authentication: Basic ").Append(String(String(uname).Append(":").Append(passwd)).EncodeBase64()).Append("\n"); connect.Append("\n"); if (send(stream, (char *) connect, connect.Length(), 0) < connect.Length()) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Receive answer. */ String answer; char c[2] = { 0, 0 }; while (!(answer.EndsWith("\n\n") || answer.EndsWith("\r\n\r\n"))) { if (recv(stream, c, 1, 0) <= 0) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } answer.Append(c); } /* Check if connect attempt was successful. */ if (answer.SubString(9, 3) != "200") { Close(); lastError = IO_ERROR_UNEXPECTED; return; } } S::IO::DriverHTTPS::~DriverHTTPS() { Close(); } S::Int S::IO::DriverHTTPS::ReadData(UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; int bytes = recv(stream, (char *) data, dataSize, 0); if (bytes <= 0) return -1; else return bytes; } S::Int S::IO::DriverHTTPS::WriteData(const UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; return send(stream, (const char *) data, dataSize, 0); } S::Bool S::IO::DriverHTTPS::Close() { #if defined __WIN32__ if (!closeStream || closesocket(stream) != 0) return False; #else if (!closeStream || close(stream) != 0) return False; #endif closeStream = False; return True; } smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/driver_memory.cpp000077500000000000000000000025311516402577000250750ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::IO::DriverMemory::DriverMemory(Void *iStream, Int iSize) : Driver() { stream = iStream; size = iSize; } S::IO::DriverMemory::~DriverMemory() { } S::Int S::IO::DriverMemory::ReadData(UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; dataSize = Math::Min(dataSize, size - position); memcpy(data, (unsigned char *) stream + position, dataSize); position += dataSize; return dataSize; } S::Int S::IO::DriverMemory::WriteData(const UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; dataSize = Math::Min(dataSize, size - position); memcpy((unsigned char *) stream + position, data, dataSize); position += dataSize; return dataSize; } S::Int64 S::IO::DriverMemory::Seek(Int64 newPosition) { if (newPosition > size) return -1; position = newPosition; return position; } smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/driver_posix.cpp000077500000000000000000000074411516402577000247340ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #if defined __WIN32__ # include # include # define open _wopen # define close _close # define read _read # define write _write # define lseek64 _lseeki64 # define ftruncate _chsize # define fsync _commit #else # include # ifndef O_CLOEXEC # define O_CLOEXEC 0 # endif # if !defined __linux__ && !defined __sun && !defined __GNU__ # define lseek64 lseek # endif #endif S::IO::DriverPOSIX::DriverPOSIX(const String &file, Int mode) : Driver() { stream = -1; closeStream = False; #if defined __WIN32__ /* Add O_NOINHERIT and O_BINARY options and Unicode prefix on Windows. */ Int options = O_NOINHERIT | O_BINARY; String fileName = Directory::MakeExtendedPath(file); #else /* Use O_CLOEXEC option on other systems. */ Int options = O_CLOEXEC; String fileName = file; /* Set output format to UTF-8 on non-Windows systems. */ String::OutputFormat outputFormat("UTF-8"); #endif switch (mode) { default: lastError = IO_ERROR_BADPARAM; return; case OS_APPEND: // open a file for appending data stream = open(fileName, options | O_RDWR | O_CREAT, 0666); if (stream != -1) { Int64 size = GetSize(); if (size >= 0) Seek(size); } break; case OS_REPLACE: // create or overwrite a file stream = open(fileName, options | O_RDWR | O_CREAT | O_TRUNC, 0666); break; case IS_READ | IS_WRITE: // open a file for reading data stream = open(fileName, options | O_RDWR); break; case IS_READ: // open a file in read only mode stream = open(fileName, options | O_RDONLY); break; } /* Check if stream was opened successfully. */ if (stream == -1) { if (errno == EACCES) lastError = IO_ERROR_NOACCESS; else lastError = IO_ERROR_UNEXPECTED; return; } streamID = fileName; closeStream = True; } S::IO::DriverPOSIX::DriverPOSIX(Int iStream) : Driver() { stream = iStream; closeStream = False; } S::IO::DriverPOSIX::~DriverPOSIX() { Close(); } S::Int S::IO::DriverPOSIX::ReadData(UnsignedByte *data, Int dataSize) { if (stream == -1 || dataSize <= 0) return 0; return read(stream, data, dataSize); } S::Int S::IO::DriverPOSIX::WriteData(const UnsignedByte *data, Int dataSize) { if (stream == -1 || dataSize <= 0) return 0; return write(stream, data, dataSize); } S::Int64 S::IO::DriverPOSIX::Seek(Int64 newPos) { if (stream == -1) return -1; return lseek64(stream, newPos, SEEK_SET); } S::Bool S::IO::DriverPOSIX::Truncate(Int64 newSize) { if (stream == -1 || ftruncate(stream, newSize) != 0) return False; return True; } S::Bool S::IO::DriverPOSIX::Flush() { if (stream == -1 || fsync(stream) != 0) return False; return True; } S::Bool S::IO::DriverPOSIX::Close() { if (stream == -1 || !closeStream || close(stream) != 0) return False; stream = -1; closeStream = False; return True; } S::Int64 S::IO::DriverPOSIX::GetSize() const { if (stream == -1) return -1; Int64 oldPos = GetPos(); Int64 size = lseek64(stream, 0, SEEK_END); lseek64(stream, oldPos, SEEK_SET); return size; } S::Int64 S::IO::DriverPOSIX::GetPos() const { if (stream == -1) return -1; return lseek64(stream, 0, SEEK_CUR); } smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/driver_socket.cpp000077500000000000000000000067271516402577000250700ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ # include #else # if defined __sun # include # endif # include # include # include # include # include #endif S::IO::DriverSocket::DriverSocket(const String &hostName, Int port) : Driver() { closeStream = False; stream = -1; size = -1; mode = MODE_SOCKET_BLOCKING; timeout = 0; if (hostName.Length() > 255) { lastError = IO_ERROR_BADPARAM; return; } /* Open TCP/IP socket. */ stream = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (stream == (unsigned) (~0)) { lastError = IO_ERROR_UNEXPECTED; return; } closeStream = True; /* Get server hostname. */ hostent *host = gethostbyname(hostName); if (host == NIL) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Connect to server. */ sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_addr = *((in_addr *) *host->h_addr_list); saddr.sin_port = htons((short) port); memset(&saddr.sin_zero, 0, sizeof(saddr.sin_zero)); if (connect(stream, (sockaddr *) &saddr, sizeof(struct sockaddr)) == -1) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } } S::IO::DriverSocket::DriverSocket(unsigned int iStream) : Driver() { size = -1; stream = iStream; closeStream = False; timeout = 0; SetMode(MODE_SOCKET_BLOCKING); } S::IO::DriverSocket::~DriverSocket() { Close(); } S::Int S::IO::DriverSocket::ReadData(UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; if (mode == MODE_SOCKET_BLOCKING && timeout != 0) { #if defined __WIN32__ TIMEVAL tv = {timeout, 0}; FD_SET sock; FD_ZERO(&sock); FD_SET(stream, &sock); if (select(0, &sock, 0, 0, &tv) != 1) return 0; #endif } int bytes = recv(stream, (char *) data, dataSize, 0); if (bytes <= 0) return -1; else return bytes; } S::Int S::IO::DriverSocket::WriteData(const UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; if (mode == MODE_SOCKET_BLOCKING && timeout != 0) { #if defined __WIN32__ TIMEVAL tv = { timeout, 0 }; FD_SET sock; FD_ZERO(&sock); FD_SET(stream, &sock); if (select(0, 0, &sock, 0, &tv) != 1) return 0; #endif } return send(stream, (const char *) data, dataSize, 0); } S::Bool S::IO::DriverSocket::Close() { #if defined __WIN32__ if (!closeStream || closesocket(stream) != 0) return False; #else if (!closeStream || close(stream) != 0) return False; #endif closeStream = False; return True; } S::Bool S::IO::DriverSocket::SetMode(Int nm) { switch (nm) { default: return False; case MODE_SOCKET_BLOCKING: case MODE_SOCKET_NONBLOCKING: mode = nm; break; } #if defined __WIN32__ if (ioctlsocket(stream, FIONBIO, &mode) != 0) return False; else return True; #else if (ioctl(stream, FIONBIO, &mode) != 0) return False; else return True; #endif } S::Bool S::IO::DriverSocket::SetTimeout(Int nt) { if (mode != MODE_SOCKET_BLOCKING) return False; if (timeout < 0) return False; timeout = nt; return True; } smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/driver_socks4.cpp000077500000000000000000000111611516402577000247720ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ # include #else # include # include # include # include # include #endif S::IO::DriverSOCKS4::DriverSOCKS4(const String &proxy, Int socksPort, const String &hostName, Int port) : Driver() { closeStream = False; stream = -1; size = -1; if (hostName == NIL || hostName.Length() > 255) { lastError = IO_ERROR_BADPARAM; return; } /* Open TCP/IP socket. */ stream = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (stream == (unsigned) (~0)) { lastError = IO_ERROR_UNEXPECTED; return; } closeStream = True; /* Get proxy and server hostname. */ hostent *host = gethostbyname(proxy); if (host == NIL) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Connect to proxy. */ sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_addr = *((in_addr *) *host->h_addr_list); saddr.sin_port = htons((short) socksPort); memset(&saddr.sin_zero, 0, sizeof(saddr.sin_zero)); if (connect(stream, (sockaddr *) &saddr, sizeof(struct sockaddr)) == -1) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Send connect request. */ hostent *server_hostent = gethostbyname(hostName); if (server_hostent != NULL) { unsigned char *socksdata = new unsigned char [9]; socksdata[0] = 4; socksdata[1] = 1; socksdata[2] = htons((short) port) % 256; socksdata[3] = htons((short) port) / 256; socksdata[4] = server_hostent->h_addr_list[0][0]; socksdata[5] = server_hostent->h_addr_list[0][1]; socksdata[6] = server_hostent->h_addr_list[0][2]; socksdata[7] = server_hostent->h_addr_list[0][3]; socksdata[8] = 0; if (send(stream, (char *) socksdata, 9, 0) < 9) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } delete [] socksdata; } else if (inet_addr(hostName) != INADDR_NONE) { unsigned char *socksdata = new unsigned char [9]; socksdata[0] = 4; socksdata[1] = 1; socksdata[2] = htons((short) port) % 256; socksdata[3] = htons((short) port) / 256; socksdata[4] = IOGetByte(inet_addr(hostName), 0); socksdata[5] = IOGetByte(inet_addr(hostName), 1); socksdata[6] = IOGetByte(inet_addr(hostName), 2); socksdata[7] = IOGetByte(inet_addr(hostName), 3); socksdata[8] = 0; if (send(stream, (char *) socksdata, 9, 0) < 9) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } delete [] socksdata; } else { Int hostNameLen = strlen(hostName); unsigned char *socksdata = new unsigned char [10 + hostNameLen]; socksdata[0] = 4; socksdata[1] = 1; socksdata[2] = htons((short) port) % 256; socksdata[3] = htons((short) port) / 256; socksdata[4] = 0; socksdata[5] = 0; socksdata[6] = 0; socksdata[7] = 1; socksdata[8] = 0; for (Int i = 0; i < hostNameLen; i++) socksdata[9 + i] = hostName[i]; socksdata[9 + hostNameLen] = 0; if (send(stream, (char *) socksdata, 10 + hostNameLen, 0) < 10 + hostNameLen) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } delete [] socksdata; } /* Receive answer. */ unsigned char *socksdata = new unsigned char [8]; int recbytes = 0; while (recbytes != 8) { int bytes = recv(stream, (char *) socksdata + recbytes, 8 - recbytes, 0); if (bytes <= 0) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } recbytes += bytes; } /* Check if connect attempt was successful. */ if (socksdata[1] != 90) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } delete [] socksdata; } S::IO::DriverSOCKS4::~DriverSOCKS4() { Close(); } S::Int S::IO::DriverSOCKS4::ReadData(UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; int bytes = recv(stream, (char *) data, dataSize, 0); if (bytes <= 0) return -1; else return bytes; } S::Int S::IO::DriverSOCKS4::WriteData(const UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; return send(stream, (const char *) data, dataSize, 0); } S::Bool S::IO::DriverSOCKS4::Close() { #if defined __WIN32__ if (!closeStream || closesocket(stream) != 0) return False; #else if (!closeStream || close(stream) != 0) return False; #endif closeStream = False; return True; } smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/driver_socks5.cpp000077500000000000000000000161431516402577000250000ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #if defined __WIN32__ # include #else # include # include # include # include #endif S::IO::DriverSOCKS5::DriverSOCKS5(const String &proxy, Int socksPort, const String &hostName, Int port, const String &uname, const String &passwd) : Driver() { closeStream = False; stream = -1; size = -1; if (hostName == NIL || hostName.Length() > 255) { lastError = IO_ERROR_BADPARAM; return; } /* Open TCP/IP socket. */ stream = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (stream == (unsigned) (~0)) { lastError = IO_ERROR_UNEXPECTED; return; } closeStream = True; /* Get proxy hostname. */ hostent *host = gethostbyname(proxy); if (host == NIL) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Connect to proxy. */ sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_addr = *((in_addr *) *host->h_addr_list); saddr.sin_port = htons((short) socksPort); memset(&saddr.sin_zero, 0, sizeof(saddr.sin_zero)); if (connect(stream, (sockaddr *) &saddr, sizeof(struct sockaddr)) == -1) { Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Send connect request. */ if (uname == NIL) { unsigned char *socksdata = new unsigned char [3]; socksdata[0] = 5; // SOCKS version 5 socksdata[1] = 1; // One authentication method socksdata[2] = 0x00; // Method 1: No authentication if (send(stream, (char *) socksdata, 3, 0) < 3) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Read and evaluate response. */ int recbytes = 0; while (recbytes != 2) { int bytes = recv(stream, (char *) socksdata + recbytes, 2 - recbytes, 0); if (bytes <= 0) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } recbytes += bytes; } /* Check if proxy requires authentication. */ if (socksdata[1] == 0xFF) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } delete [] socksdata; } else { unsigned char *socksdata = new unsigned char [4]; socksdata[0] = 5; // SOCKS version 5 socksdata[1] = 2; // Two authentication methods socksdata[2] = 0x00; // Method 0x00: No authentication socksdata[3] = 0x02; // Method 0x02: Username / password if (send(stream, (char *) socksdata, 4, 0) < 4) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Read and evaluate response. */ int recbytes = 0; while (recbytes != 2) { int bytes = recv(stream, (char *) socksdata + recbytes, 2 - recbytes, 0); if (bytes <= 0) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } recbytes += bytes; } /* Check if proxy accepted authentication method. */ if (socksdata[1] == 0xFF) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } if (socksdata[1] == 0x02) { /* Method 0x02: Username / password */ delete [] socksdata; Int unameLen = strlen(uname); Int passwdLen = passwd != NIL ? strlen(passwd) : 0; socksdata = new unsigned char [3 + unameLen + passwdLen]; socksdata[0] = 1; socksdata[1] = unameLen; for (Int i = 0; i < unameLen; i++) socksdata[2 + i] = uname[i]; socksdata[2 + unameLen] = passwdLen; for (Int i = 0; i < passwdLen; i++) socksdata[3 + unameLen + i] = passwd[i]; if (send(stream, (char *) socksdata, 3 + unameLen + passwdLen, 0) < 3 + unameLen + passwdLen) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Read and evaluate response. */ int recbytes = 0; while (recbytes != 2) { int bytes = recv(stream, (char *) socksdata + recbytes, 2 - recbytes, 0); if (bytes <= 0) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } recbytes += bytes; } /* Check if proxy accepted username/password. */ if (socksdata[1] != 0x00) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } } delete [] socksdata; } /* Send connect request. */ unsigned char *socksdata = new unsigned char [5 + 255 + 2]; Int hostNameLen = strlen(hostName); socksdata[0] = 5; // SOCKS version 5 socksdata[1] = 0x01; // Command: Connect socksdata[2] = 0x00; // Reserved field socksdata[3] = 0x03; // Connect type: Domain name socksdata[4] = hostNameLen; for (Int i = 0; i < hostNameLen; i++) socksdata[5 + i] = hostName[i]; socksdata[5 + hostNameLen] = htons((short) port) % 256; socksdata[6 + hostNameLen] = htons((short) port) / 256; if (send(stream, (char *) socksdata, 7 + hostNameLen, 0) < 7 + hostNameLen) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Receive and evaluate first 4 bytes of answer. */ int recbytes = 0; while (recbytes != 4) { int bytes = recv(stream, (char *) socksdata + recbytes, 4 - recbytes, 0); if (bytes <= 0) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } recbytes += bytes; } /* Check if connect attempt was successful. */ if (socksdata[1] != 0x00) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Receive rest of answer. */ if (socksdata[3] == 0x01) { /* Read IP address and port. */ int recbytes = 0; while (recbytes != 6) { int bytes = recv(stream, (char *) socksdata + 4 + recbytes, 6 - recbytes, 0); if (bytes <= 0) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } recbytes += bytes; } } else if (socksdata[3] == 0x03) { /* Read length of hostname. */ if (recv(stream, (char *) socksdata + 4, 1, 0) <= 0) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } /* Read hostname and port. */ int neededbytes = Math::Min(255, socksdata[4]) + 2; int recbytes = 0; while (recbytes != neededbytes) { int bytes = recv(stream, (char *) socksdata + 5 + recbytes, neededbytes - recbytes, 0); if (bytes <= 0) { delete [] socksdata; Close(); lastError = IO_ERROR_UNEXPECTED; return; } recbytes += bytes; } } delete [] socksdata; } S::IO::DriverSOCKS5::~DriverSOCKS5() { Close(); } S::Int S::IO::DriverSOCKS5::ReadData(UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; int bytes = recv(stream, (char *) data, dataSize, 0); if (bytes <= 0) return -1; else return bytes; } S::Int S::IO::DriverSOCKS5::WriteData(const UnsignedByte *data, Int dataSize) { if (dataSize <= 0) return 0; return send(stream, (const char *) data, dataSize, 0); } S::Bool S::IO::DriverSOCKS5::Close() { #if defined __WIN32__ if (!closeStream || closesocket(stream) != 0) return False; #else if (!closeStream || close(stream) != 0) return False; #endif closeStream = False; return True; } smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/driver_win32.cpp000077500000000000000000000101271516402577000245270ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include S::IO::DriverWin32::DriverWin32(const String &file, Int mode) : Driver() { stream = INVALID_HANDLE_VALUE; closeStream = False; /* Build real filename to pass to CreateFile. */ String fileName = Directory::MakeExtendedPath(file); switch (mode) { default: lastError = IO_ERROR_BADPARAM; return; case OS_APPEND: // open a file for appending data stream = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (stream != INVALID_HANDLE_VALUE) { Int64 size = GetSize(); if (size >= 0) Seek(size); } break; case OS_REPLACE: // create or overwrite a file stream = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); break; case IS_READ | IS_WRITE: // open a file for reading data stream = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); break; case IS_READ: // open a file in read only mode stream = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); break; } /* Check if stream was opened successfully. */ if (stream == INVALID_HANDLE_VALUE) { if (::GetLastError() == ERROR_ACCESS_DENIED) lastError = IO_ERROR_NOACCESS; else lastError = IO_ERROR_UNEXPECTED; return; } closeStream = True; } S::IO::DriverWin32::DriverWin32(HANDLE iStream) : Driver() { stream = iStream; closeStream = False; } S::IO::DriverWin32::~DriverWin32() { Close(); } S::Int S::IO::DriverWin32::ReadData(UnsignedByte *data, Int dataSize) { if (stream == INVALID_HANDLE_VALUE || dataSize <= 0) return 0; DWORD bytes; ReadFile(stream, data, dataSize, &bytes, NULL); return bytes; } S::Int S::IO::DriverWin32::WriteData(const UnsignedByte *data, Int dataSize) { if (stream == INVALID_HANDLE_VALUE || dataSize <= 0) return 0; DWORD bytes; WriteFile(stream, data, dataSize, &bytes, NULL); return bytes; } S::Int64 S::IO::DriverWin32::Seek(Int64 newPos) { if (stream == INVALID_HANDLE_VALUE) return -1; LONG hi32 = newPos >> 32; DWORD lo32 = SetFilePointer(stream, newPos, &hi32, FILE_BEGIN); if (lo32 == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR) return -1; return (Int64) hi32 << 32 | lo32; } S::Bool S::IO::DriverWin32::Truncate(Int64 newSize) { if (stream == INVALID_HANDLE_VALUE || Seek(newSize) == -1 || !SetEndOfFile(stream)) return False; return True; } S::Bool S::IO::DriverWin32::Flush() { if (stream == INVALID_HANDLE_VALUE || !FlushFileBuffers(stream)) return False; return True; } S::Bool S::IO::DriverWin32::Close() { if (stream == INVALID_HANDLE_VALUE || !closeStream || !CloseHandle(stream)) return False; stream = INVALID_HANDLE_VALUE; closeStream = False; return True; } S::Int64 S::IO::DriverWin32::GetSize() const { if (stream == INVALID_HANDLE_VALUE) return -1; DWORD hi32 = 0; DWORD lo32 = GetFileSize(stream, &hi32); if (lo32 == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR) return -1; return (Int64) hi32 << 32 | lo32; } S::Int64 S::IO::DriverWin32::GetPos() const { if (stream == INVALID_HANDLE_VALUE) return -1; LONG hi32 = 0; DWORD lo32 = SetFilePointer(stream, 0, &hi32, FILE_CURRENT); if (lo32 == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR) return -1; return (Int64) hi32 << 32 | lo32; } smooth-0.9.11~git20260403.0230c0da/classes/io/drivers/driver_zero.cpp000077500000000000000000000011221516402577000245370ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::IO::DriverZero::DriverZero() : Driver() { } S::IO::DriverZero::~DriverZero() { } smooth-0.9.11~git20260403.0230c0da/classes/io/filter.cpp000077500000000000000000000021301516402577000220140ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::IO::Filter::Filter() { driver = NIL; packageSize = 0; } S::IO::Filter::~Filter() { } S::Bool S::IO::Filter::Activate() { return True; } S::Bool S::IO::Filter::Deactivate() { return True; } S::Int S::IO::Filter::WriteData(const Buffer &data) { if (driver == NIL) return -1; return driver->WriteData(data, data.Size()); } S::Int S::IO::Filter::ReadData(Buffer &data) { if (driver == NIL) return -1; if (data.Size() > (driver->GetSize() - driver->GetPos())) data.Resize(driver->GetSize() - driver->GetPos()); return driver->ReadData(data, data.Size()); } smooth-0.9.11~git20260403.0230c0da/classes/io/filters/000077500000000000000000000000001516402577000214745ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/io/filters/Makefile000066400000000000000000000011061516402577000231320ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifeq ($(USE_BUNDLED_LIBBZ2),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support/libbz2 else MYCCOPTS += -I/usr/local/include endif # Enter object files here: OBJECTS = filter_bzip2.o filter_xor.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/io/filters/filter_bzip2.cpp000077500000000000000000000033001516402577000245720ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::IO::FilterBZip2::FilterBZip2() { packageSize = -1; } S::IO::FilterBZip2::~FilterBZip2() { } S::Int S::IO::FilterBZip2::WriteData(const Buffer &data) { if (driver == NIL) return -1; int outsize = data.Size() + data.Size() / 100 + 1000; unsigned char *dest = new unsigned char [outsize]; BZ2_bzBuffToBuffCompress((char *) dest, (unsigned int *) &outsize, const_cast((const char *) (const UnsignedByte *) data), data.Size(), 5, 0, 0); driver->WriteData(dest, outsize); delete [] dest; return outsize; } S::Int S::IO::FilterBZip2::ReadData(Buffer &data) { if (driver == NIL) return -1; /* Try guessing the size of uncompressed data. */ int size = data.Size(); int outsize; if (size < (200 * 1024)) outsize = size * 100 + 10000; else if (size > (20 * 1024 * 1024)) outsize = size * 5 + 10000; else outsize = size * 10 + 10000; /* Now decompress. */ unsigned char *src = new unsigned char [size]; driver->ReadData(src, size); data.Resize(outsize); BZ2_bzBuffToBuffDecompress((char *) (UnsignedByte *) data, (unsigned int *) &outsize, (char *) src, size, 0, 0); delete [] src; return outsize; } smooth-0.9.11~git20260403.0230c0da/classes/io/filters/filter_xor.cpp000077500000000000000000000024451516402577000243650ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::IO::FilterXOR::FilterXOR() { packageSize = 4; modifier = 0; } S::IO::FilterXOR::~FilterXOR() { } S::Int S::IO::FilterXOR::WriteData(const Buffer &data) { if (driver == NIL) return -1; Int value = (data[3] + 256 * data[2] + 65536 * data[1] + 16777216 * data[0]) ^ modifier; return driver->WriteData((UnsignedByte *) &value, 4); } S::Int S::IO::FilterXOR::ReadData(Buffer &data) { if (driver == NIL) return -1; driver->ReadData(data, data.Size()); Int value = (data[3] + 256 * data[2] + 65536 * data[1] + 16777216 * data[0]) ^ modifier; data[0] = (value >> 24) & 255; data[1] = (value >> 16) & 255; data[2] = (value >> 8) & 255; data[3] = value & 255; return data.Size(); } S::Void S::IO::FilterXOR::SetModifier(Int mod) { modifier = mod; } smooth-0.9.11~git20260403.0230c0da/classes/io/instream.cpp000077500000000000000000000323661516402577000223670ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2023 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include S::Int S::IO::InStream::defaultPackageSize = 4096; S::IO::InStream::InStream(Int type, Driver *iDriver) { outStream = NIL; if (type != STREAM_DRIVER) { lastError = IO_ERROR_BADPARAM; return; } driver = iDriver; if (driver->GetLastError() != IO_ERROR_OK) { lastError = driver->GetLastError(); return; } streamType = STREAM_DRIVER; size = driver->GetSize(); closefile = False; packageSize = defaultPackageSize; stdpacksize = packageSize; origpacksize = packageSize; currentBufferPos = defaultPackageSize; origsize = size; } S::IO::InStream::InStream(Int type, const String &fileName, Int mode) { outStream = NIL; if (type != STREAM_FILE) { lastError = IO_ERROR_BADPARAM; return; } if (Directory(fileName).Exists()) { lastError = IO_ERROR_BADPARAM; return; } driver = new DriverANSI(File(fileName), mode); if (driver->GetLastError() != IO_ERROR_OK) { lastError = driver->GetLastError(); delete driver; return; } streamType = STREAM_DRIVER; size = driver->GetSize(); packageSize = defaultPackageSize; stdpacksize = packageSize; origpacksize = packageSize; currentBufferPos = defaultPackageSize; origsize = size; } S::IO::InStream::InStream(Int type, FILE *openFile) { outStream = NIL; if (type != STREAM_ANSI) { lastError = IO_ERROR_BADPARAM; return; } driver = new DriverANSI(openFile); if (driver->GetLastError() != IO_ERROR_OK) { lastError = driver->GetLastError(); delete driver; return; } streamType = STREAM_DRIVER; size = driver->GetSize(); currentFilePos = driver->GetPos(); currentBufferPos = defaultPackageSize; origsize = size; } S::IO::InStream::InStream(Int type, Void *inBuffer, Long bufferSize) { outStream = NIL; if (type != STREAM_BUFFER) { lastError = IO_ERROR_BADPARAM; return; } driver = new DriverMemory(inBuffer, bufferSize); if (driver->GetLastError() != IO_ERROR_OK) { lastError = driver->GetLastError(); delete driver; return; } streamType = STREAM_DRIVER; size = driver->GetSize(); currentBufferPos = packageSize; origsize = size; } S::IO::InStream::InStream(Int type, OutStream *out) { outStream = NIL; if (type != STREAM_STREAM) { lastError = IO_ERROR_BADPARAM; return; } if (out->streamType == STREAM_NONE || out->crosslinked) { lastError = IO_ERROR_OPNOTAVAIL; return; } streamType = STREAM_STREAM; crosslinked = True; outStream = out; outStream->inStream = this; outStream->crosslinked = True; packageSize = defaultPackageSize; stdpacksize = packageSize; origpacksize = packageSize; if (outStream->streamType == STREAM_DRIVER) { driver = outStream->driver; streamType = STREAM_DRIVER; size = outStream->size; currentFilePos = outStream->currentFilePos; closefile = False; packageSize = 1; stdpacksize = packageSize; origpacksize = packageSize; currentBufferPos = packageSize; origsize = size; } } S::IO::InStream::~InStream() { /* Close stream. */ Close(); } S::Bool S::IO::InStream::ReadData() { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (streamType != STREAM_DRIVER) return True; /* Loop until we have some data. */ Int decsize = 0; do { packageSize = stdpacksize; size = origsize; currentFilePos = origfilepos; if (filter == NIL) { /* Read unfiltered data. */ driver->Seek(currentFilePos); if (size != -1) dataBuffer.Resize(packageSize < size - currentFilePos ? packageSize : size - currentFilePos); else dataBuffer.Resize(packageSize); decsize = driver->ReadData(dataBuffer, dataBuffer.Size()); } else { /* Read filtered data. */ if (filter->GetPackageSize() > 0) packageSize = filter->GetPackageSize(); dataBuffer.Resize(packageSize); decsize = filter->ReadData(dataBuffer); } /* Update package size and buffer positions. */ if (packageSize <= size - currentFilePos || filter != NIL || size == -1) { if (decsize == -1) { packageSize = 0; return False; } packageSize = decsize; origfilepos = currentFilePos + packageSize; if (packageSize + currentFilePos > size && size != -1) size = packageSize + currentFilePos; } else { packageSize = decsize; if (decsize <= 0) { packageSize = 0; return False; } } currentBufferPos = 0; /* Bail out if more data is requested, but we do not have any more. */ if (packageSize == 0 && driver->GetPos() == driver->GetSize()) return False; } while (packageSize == 0); return True; } S::Int64 S::IO::InStream::InputNumber(Int bytes) // Intel byte order DCBA { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return -1; } if (bytes > 8 || bytes < 0) { lastError = IO_ERROR_BADPARAM; return -1; } if (bitstreamActive && !keepBits) CompleteBitstream(); Int64 rval = 0; for (Int i = 0; i < bytes; i++) { if (currentFilePos >= (origfilepos + packageSize)) { lastError = IO_ERROR_UNKNOWN; return -1; } while (currentBufferPos >= packageSize) { if (!ReadData()) { lastError = IO_ERROR_NODATA; return -1; } } if (bytes <= 4) rval += dataBuffer[currentBufferPos] * (1 << (i * 8)); else rval += dataBuffer[currentBufferPos] * (1LL << (i * 8)); currentBufferPos++; currentFilePos++; } return rval; } S::Int64 S::IO::InStream::InputNumberRaw(Int bytes) // Raw byte order ABCD { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return -1; } if (bytes > 8 || bytes < 0) { lastError = IO_ERROR_BADPARAM; return -1; } if (bitstreamActive && !keepBits) CompleteBitstream(); Int64 rval = 0; for (Int i = bytes - 1; i >= 0; i--) { if (currentFilePos >= (origfilepos + packageSize)) { lastError = IO_ERROR_UNKNOWN; return -1; } while (currentBufferPos >= packageSize) { if (!ReadData()) { lastError = IO_ERROR_NODATA; return -1; } } if (bytes <= 4) rval += dataBuffer[currentBufferPos] * (1 << (i * 8)); else rval += dataBuffer[currentBufferPos] * (1LL << (i * 8)); currentBufferPos++; currentFilePos++; } return rval; } S::Int64 S::IO::InStream::InputBits(Int bits) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return -1; } if (bits > 64 || bits < 0) { lastError = IO_ERROR_BADPARAM; return -1; } if (!bitstreamActive) InitBitstream(); Int64 rval = 0; while (bitLength < bits) { if (currentFilePos >= (origfilepos + packageSize)) { lastError = IO_ERROR_UNKNOWN; return -1; } while (currentBufferPos >= packageSize) { if (!ReadData()) { lastError = IO_ERROR_NODATA; return -1; } } for (Int i = 0; i < 8; i++) { bitBuffer[bitLength] = IOGetBit(dataBuffer[currentBufferPos], i); bitLength++; } currentBufferPos++; currentFilePos++; } for (Int i = 0; i < bits; i++) { rval = rval | (Int64(bitBuffer[i]) << i); } bitLength = bitLength - bits; for (Int i = 0; i < bitLength; i++) { bitBuffer[i] = bitBuffer[i + bits]; } return rval; } S::String S::IO::InStream::InputString(Int bytes) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return NIL; } if (bytes <= 0) { lastError = IO_ERROR_BADPARAM; return NIL; } if (bitstreamActive && !keepBits) CompleteBitstream(); Int bytesleft = bytes; Int databufferpos = 0; Buffer stringBuffer(bytes + 1); while (bytesleft) { if (currentFilePos >= (origfilepos + packageSize)) { lastError = IO_ERROR_UNKNOWN; return NIL; } while (currentBufferPos >= packageSize) { /* If no more data is available, set lastError and return NIL. */ if (!ReadData()) { lastError = IO_ERROR_NODATA; return NIL; } } /* Get amount of data read and copy to string buffer. */ Int amount = ((packageSize - currentBufferPos) < (bytesleft)) ? (packageSize - currentBufferPos) : (bytesleft); memcpy((UnsignedByte *) stringBuffer + databufferpos, (UnsignedByte *) dataBuffer + currentBufferPos, amount); bytesleft -= amount; databufferpos += amount; currentBufferPos += amount; currentFilePos += amount; } stringBuffer[bytes] = 0; return String((char *) (UnsignedByte *) stringBuffer); } S::String S::IO::InStream::InputLine() { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return NIL; } if (bitstreamActive && !keepBits) CompleteBitstream(); Long inpval; Int bytes = 0; Buffer stringBuffer(1024); while (True) { for (Int i = 0; i < 1024; i++) { inpval = InputNumber(1); if (inpval == 0 || inpval == -1) { stringBuffer[bytes] = 0; return String((char *) (UnsignedByte *) stringBuffer); } if (inpval != 13 && inpval != 10) { stringBuffer[bytes++] = (char) inpval; } else { if (inpval == 13) InputNumber(1); stringBuffer[bytes] = 0; return String((char *) (UnsignedByte *) stringBuffer); } } stringBuffer.Resize(bytes + 1024); } return NIL; // never reached } S::Int S::IO::InStream::InputData(Void *pointer, Int bytes) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return 0; } if (bytes > 0 && pointer == NIL) { lastError = IO_ERROR_BADPARAM; return 0; } if (bytes < 0) { lastError = IO_ERROR_BADPARAM; return 0; } if (bitstreamActive && !keepBits) CompleteBitstream(); Int bytesleft = bytes; Int databufferpos = 0; while (bytesleft) { if (currentFilePos >= (origfilepos + packageSize)) { lastError = IO_ERROR_UNKNOWN; return bytes - bytesleft; } while (currentBufferPos >= packageSize) { /* If no more data is available, set lastError and * return the number of bytes actually read. */ if (!ReadData()) { lastError = IO_ERROR_NODATA; return bytes - bytesleft; } } /* Get amount of data read and copy to output buffer. */ Int amount = ((packageSize - currentBufferPos) < (bytesleft)) ? (packageSize - currentBufferPos) : (bytesleft); memcpy((UnsignedByte *) pointer + databufferpos, (UnsignedByte *) dataBuffer + currentBufferPos, amount); bytesleft -= amount; databufferpos += amount; currentBufferPos += amount; currentFilePos += amount; } return bytes; } S::Bool S::IO::InStream::InitBitstream() { bitLength = 0; bitstreamActive = 1; return True; } S::Bool S::IO::InStream::CompleteBitstream() { bitLength = 0; bitstreamActive = 0; return True; } S::Bool S::IO::InStream::SetPackageSize(Int newPackageSize) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (!allowpackset) { lastError = IO_ERROR_OPNOTAVAIL; return False; } if (newPackageSize <= 0) { lastError = IO_ERROR_BADPARAM; return False; } if (bitstreamActive) CompleteBitstream(); packageSize = newPackageSize; stdpacksize = packageSize; currentBufferPos = packageSize; Seek(currentFilePos); return True; } S::Bool S::IO::InStream::SetFilter(Filter *newFilter) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (filter != NIL) { lastError = IO_ERROR_BADPARAM; return False; } newFilter->SetDriver(driver); Seek(currentFilePos); if (newFilter->Activate() == False) { lastError = IO_ERROR_UNKNOWN; return False; } allowpackset = True; if (newFilter->GetPackageSize() > 0) SetPackageSize(newFilter->GetPackageSize()); else if (newFilter->GetPackageSize() == -1) SetPackageSize(size - currentFilePos); allowpackset = False; filter = newFilter; return True; } S::Bool S::IO::InStream::RemoveFilter() { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (filter == NIL) { lastError = IO_ERROR_BADPARAM; return False; } filter->Deactivate(); filter = NIL; allowpackset = True; SetPackageSize(origpacksize); return True; } S::Bool S::IO::InStream::Close() { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (bitstreamActive) CompleteBitstream(); while (filter != NIL) RemoveFilter(); if (crosslinked) { if (closefile) outStream->closefile = True; outStream->crosslinked = False; outStream->inStream = NIL; closefile = False; } if (closefile) delete driver; streamType = STREAM_NONE; return True; } S::Bool S::IO::InStream::Seek(Int64 position) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (bitstreamActive) CompleteBitstream(); Int64 offset = position - currentFilePos; if (currentBufferPos + offset >= 0 && currentBufferPos + offset <= packageSize) { currentFilePos = position; currentBufferPos += offset; } else { if (driver->Seek(position) == -1) return False; currentFilePos = position; currentBufferPos = packageSize; origfilepos = currentFilePos; } return True; } S::Bool S::IO::InStream::RelSeek(Int64 offset) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } return Seek(currentFilePos + offset); } smooth-0.9.11~git20260403.0230c0da/classes/io/outstream.cpp000077500000000000000000000316151516402577000225640ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2023 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include S::Int S::IO::OutStream::defaultPackageSize = 131072; S::IO::OutStream::OutStream(Int type, Driver *iDriver) { inStream = NIL; if (type != STREAM_DRIVER) { lastError = IO_ERROR_BADPARAM; return; } driver = iDriver; if (driver->GetLastError() != IO_ERROR_OK) { lastError = driver->GetLastError(); return; } streamType = STREAM_DRIVER; size = driver->GetSize(); currentFilePos = driver->GetPos(); closefile = False; packageSize = defaultPackageSize; stdpacksize = packageSize; origpacksize = packageSize; dataBuffer.Resize(packageSize); } S::IO::OutStream::OutStream(Int type, const String &fileName, Int mode) { inStream = NIL; if (type != STREAM_FILE) { lastError = IO_ERROR_BADPARAM; return; } if (Directory(fileName).Exists()) { lastError = IO_ERROR_BADPARAM; return; } driver = new DriverANSI(File(fileName), mode); if (driver->GetLastError() != IO_ERROR_OK) { lastError = driver->GetLastError(); delete driver; return; } streamType = STREAM_DRIVER; size = driver->GetSize(); currentFilePos = size; packageSize = defaultPackageSize; stdpacksize = packageSize; origpacksize = packageSize; dataBuffer.Resize(packageSize); } S::IO::OutStream::OutStream(Int type, FILE *openFile) { inStream = NIL; if (type != STREAM_ANSI) { lastError = IO_ERROR_BADPARAM; return; } driver = new DriverANSI(openFile); if (driver->GetLastError() != IO_ERROR_OK) { lastError = driver->GetLastError(); delete driver; return; } streamType = STREAM_DRIVER; size = driver->GetSize(); currentFilePos = driver->GetPos(); dataBuffer.Resize(packageSize); } S::IO::OutStream::OutStream(Int type, Void *outBuffer, Long bufferSize) { inStream = NIL; if (type != STREAM_BUFFER) { lastError = IO_ERROR_BADPARAM; return; } driver = new DriverMemory(outBuffer, bufferSize); if (driver->GetLastError() != IO_ERROR_OK) { lastError = driver->GetLastError(); delete driver; return; } streamType = STREAM_DRIVER; size = driver->GetSize(); dataBuffer.Resize(packageSize); } S::IO::OutStream::OutStream(Int type, InStream *in) { inStream = NIL; if (type != STREAM_STREAM) { lastError = IO_ERROR_BADPARAM; return; } if (in->streamType == STREAM_NONE || in->crosslinked) { lastError = IO_ERROR_OPNOTAVAIL; return; } streamType = STREAM_STREAM; crosslinked = True; inStream = in; inStream->outStream = this; inStream->crosslinked = True; packageSize = defaultPackageSize; stdpacksize = packageSize; origpacksize = packageSize; if (inStream->streamType == STREAM_DRIVER) { driver = inStream->driver; streamType = STREAM_DRIVER; size = inStream->origsize; currentFilePos = inStream->currentFilePos; closefile = False; packageSize = 1; stdpacksize = packageSize; origpacksize = packageSize; dataBuffer.Resize(packageSize); } } S::IO::OutStream::~OutStream() { /* Close stream; ignore return value. */ Close(); } S::Bool S::IO::OutStream::Flush() { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (packageSize <= 0) { lastError = IO_ERROR_UNKNOWN; return False; } if (currentBufferPos <= 0) return True; if (bitstreamActive) CompleteBitstream(); Int ps = packageSize; Int oldcpos = currentBufferPos; if (filter != NIL && filter->GetPackageSize() > 0) { for (Int i = 0; i < (packageSize - oldcpos); i++) OutputNumber(0, 1); } if (currentBufferPos > 0) { packageSize = currentBufferPos; if (!WriteData()) { packageSize = ps; { lastError = IO_ERROR_UNKNOWN; return False; } } packageSize = ps; } return True; } S::Bool S::IO::OutStream::WriteData() { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (packageSize <= 0) { lastError = IO_ERROR_UNKNOWN; return False; } if (currentBufferPos < packageSize) return True; if (filter != NIL && filter->GetPackageSize() == -1) { dataBuffer.Resize(packageSize + defaultPackageSize); packageSize += defaultPackageSize; stdpacksize = packageSize; return True; } if (streamType == STREAM_DRIVER) { Int encsize = 0; dataBuffer.Resize(packageSize); if (filter == NIL) encsize = driver->WriteData(dataBuffer, packageSize); else encsize = filter->WriteData(dataBuffer); if (encsize == -1) { packageSize = 0; return False; } driver->Flush(); if (size == currentFilePos) size -= (packageSize - encsize); currentFilePos -= (packageSize - encsize); currentBufferPos -= packageSize; } return True; } S::Bool S::IO::OutStream::OutputNumber(Int64 number, Int bytes) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (packageSize <= 0) { lastError = IO_ERROR_UNKNOWN; return False; } if (bytes > 8 || bytes < 0) { lastError = IO_ERROR_BADPARAM; return False; } if (bitstreamActive && !keepBits) CompleteBitstream(); for (Int i = 0; i < bytes; i++) { if (currentBufferPos >= packageSize) { if (!WriteData()) { lastError = IO_ERROR_UNKNOWN; return False; } } dataBuffer[currentBufferPos] = IOGetByte(number, i); if (currentFilePos == size) size++; currentBufferPos++; currentFilePos++; } if (currentBufferPos >= packageSize) { if (!WriteData()) { lastError = IO_ERROR_UNKNOWN; return False; } } return True; } S::Bool S::IO::OutStream::OutputNumberRaw(Int64 number, Int bytes) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (packageSize <= 0) { lastError = IO_ERROR_UNKNOWN; return False; } if (bytes > 8 || bytes < 0) { lastError = IO_ERROR_BADPARAM; return False; } if (bitstreamActive && !keepBits) CompleteBitstream(); for (Int i = bytes - 1; i >= 0; i--) { if (currentBufferPos >= packageSize) { if (!WriteData()) { lastError = IO_ERROR_UNKNOWN; return False; } } dataBuffer[currentBufferPos] = IOGetByte(number, i); if (currentFilePos == size) size++; currentBufferPos++; currentFilePos++; } if (currentBufferPos >= packageSize) { if (!WriteData()) { lastError = IO_ERROR_UNKNOWN; return False; } } return True; } S::Bool S::IO::OutStream::OutputBits(Int64 number, Int bits) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (packageSize <= 0) { lastError = IO_ERROR_UNKNOWN; return False; } if (bits > 64 || bits < 0) { lastError = IO_ERROR_BADPARAM; return False; } if (!bitstreamActive) InitBitstream(); for (Int j = 0; j < bits; j++) { bitBuffer[bitLength] = IOGetBit(number, j); bitLength++; } while (bitLength >= 8) { unsigned char out = 0; for (Int i = 0; i < 8; i++) out = out | (bitBuffer[i] << i); bitLength = bitLength - 8; for (Int j = 0; j < bitLength; j++) bitBuffer[j] = bitBuffer[j + 8]; dataBuffer[currentBufferPos] = out; if (currentFilePos == size) size++; currentBufferPos++; currentFilePos++; if (currentBufferPos >= packageSize) { if (!WriteData()) { lastError = IO_ERROR_UNKNOWN; return False; } } } return True; } S::Bool S::IO::OutStream::OutputString(const String &string) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (packageSize <= 0) { lastError = IO_ERROR_UNKNOWN; return False; } if (string == NIL) { lastError = IO_ERROR_BADPARAM; return False; } if (bitstreamActive && !keepBits) CompleteBitstream(); /* Convert the string to char * here once to avoid * having to convert it again and again later. */ const char *value = string; Int bytesleft = strlen(value); Int databufferpos = 0; while (bytesleft) { Int amount = ((packageSize - currentBufferPos) < (bytesleft)) ? (packageSize - currentBufferPos) : (bytesleft); memcpy((UnsignedByte *) dataBuffer + currentBufferPos, value + databufferpos, amount); bytesleft -= amount; databufferpos += amount; currentBufferPos += amount; currentFilePos += amount; if (size < currentFilePos) size = currentFilePos; if (!WriteData()) { lastError = IO_ERROR_UNKNOWN; return False; } } return True; } S::Bool S::IO::OutStream::OutputLine(const String &string) { if (string != NIL && !OutputString(string)) return False; #if (defined __WIN32__ || defined MSDOS) && !defined __CYGWIN32__ OutputNumber(13, 1); #endif OutputNumber(10, 1); return True; } S::Bool S::IO::OutStream::OutputData(const Void *pointer, Int bytes) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (packageSize <= 0) { lastError = IO_ERROR_UNKNOWN; return False; } if (bytes > 0 && pointer == NIL) { lastError = IO_ERROR_BADPARAM; return False; } if (bytes < 0) { lastError = IO_ERROR_BADPARAM; return False; } if (bitstreamActive && !keepBits) CompleteBitstream(); Int bytesleft = bytes; Int databufferpos = 0; while (bytesleft) { Int amount = ((packageSize - currentBufferPos) < (bytesleft)) ? (packageSize - currentBufferPos) : (bytesleft); memcpy((UnsignedByte *) dataBuffer + currentBufferPos, (UnsignedByte *) pointer + databufferpos, amount); bytesleft -= amount; databufferpos += amount; currentBufferPos += amount; currentFilePos += amount; if (size < currentFilePos) size = currentFilePos; if (!WriteData()) { lastError = IO_ERROR_UNKNOWN; return False; } } return True; } S::Bool S::IO::OutStream::InitBitstream() { bitLength = 0; bitstreamActive = 1; return True; } S::Bool S::IO::OutStream::CompleteBitstream() { if (bitLength > 0) { Int out = 0; for (Int i = 0; i < 8; i++) { if (i < bitLength) out = out | (bitBuffer[i] << i); } keepBits = True; OutputNumber(out, 1); keepBits = False; } bitstreamActive = 0; return True; } S::Bool S::IO::OutStream::SetPackageSize(Int newPackageSize) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (!allowpackset) { lastError = IO_ERROR_OPNOTAVAIL; return False; } if (newPackageSize <= 0) { lastError = IO_ERROR_BADPARAM; return False; } Flush(); dataBuffer.Resize(newPackageSize); packageSize = newPackageSize; stdpacksize = packageSize; return True; } S::Bool S::IO::OutStream::SetFilter(Filter *newFilter) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (filter != NIL) { lastError = IO_ERROR_BADPARAM; return False; } newFilter->SetDriver(driver); if (newFilter->Activate() == False) { lastError = IO_ERROR_UNKNOWN; return False; } if (bitstreamActive && !keepBits) CompleteBitstream(); Flush(); filter = newFilter; allowpackset = True; if (filter->GetPackageSize() > 0) { SetPackageSize(filter->GetPackageSize()); // package size must be eqv filter size allowpackset = False; } else if (filter->GetPackageSize() == -1) { SetPackageSize(defaultPackageSize); allowpackset = False; } return True; } S::Bool S::IO::OutStream::RemoveFilter() { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (filter == NIL) { lastError = IO_ERROR_BADPARAM; return False; } if (bitstreamActive && !keepBits) CompleteBitstream(); Int oldcpos = currentBufferPos; if (filter->GetPackageSize() > 0 && currentBufferPos != 0) { for (Int i = 0; i < (packageSize - oldcpos); i++) OutputNumber(0, 1); } else { if (filter->GetPackageSize() == -1) allowpackset = True; Flush(); } allowpackset = True; filter->Deactivate(); filter = NIL; SetPackageSize(origpacksize); return True; } S::Bool S::IO::OutStream::Close() { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } while (filter != NIL) RemoveFilter(); Flush(); if (crosslinked) { if (closefile) inStream->closefile = True; inStream->crosslinked = False; inStream->outStream = NIL; closefile = False; } if (closefile) delete driver; streamType = STREAM_NONE; return True; } S::Bool S::IO::OutStream::Seek(Int64 position) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } Flush(); if (driver->Seek(position) == -1) return False; currentFilePos = position; currentBufferPos = 0; return True; } S::Bool S::IO::OutStream::RelSeek(Int64 offset) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } return Seek(currentFilePos + offset); } S::Bool S::IO::OutStream::Truncate(Int64 size) { if (streamType == STREAM_NONE) { lastError = IO_ERROR_NOTOPEN; return False; } if (!driver->Truncate(size)) return False; Seek(size); return True; } smooth-0.9.11~git20260403.0230c0da/classes/io/stream.cpp000077500000000000000000000017171516402577000220340ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::IO::Stream::Stream() { streamType = STREAM_NONE; size = 0; currentFilePos = 0; currentBufferPos = 0; bitstreamActive = False; keepBits = False; bitLength = 0; closefile = True; crosslinked = False; driver = NIL; filter = NIL; allowpackset = True; packageSize = 1; stdpacksize = packageSize; origpacksize = packageSize; origsize = 0; origfilepos = 0; lastError = IO_ERROR_OK; memset(&bitBuffer, 0, sizeof(bitBuffer)); } S::IO::Stream::~Stream() { } smooth-0.9.11~git20260403.0230c0da/classes/misc/000077500000000000000000000000001516402577000203505ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/misc/Makefile000066400000000000000000000015141516402577000220110ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifeq ($(USE_BUNDLED_LIBICONV),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support/libiconv else MYCCOPTS += -I/usr/local/include endif # Enter object files here: OBJECTS = args.o array.o binary.o config.o datetime.o math.o memory.o number.o string.o string_case.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,encoding) ALLCMD2 = $(call makein,hash) CLEANCMD1 = $(call cleanin,encoding) CLEANCMD2 = $(call cleanin,hash) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/misc/args.cpp000077500000000000000000000025121516402577000220130ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::ArgumentsParser::ArgumentsParser(int argc, char **argv) { command = argv[0]; for (Int i = 1; i < argc; i++) { #ifdef __APPLE__ if (strncmp(argv[i], "-psn_", 5) == 0) continue; #endif args.Add(argv[i]); } } S::ArgumentsParser::ArgumentsParser(const String &commandLine) { String param; Bool quoted = False; Bool first = True; for (Int i = 0, j = 0; i <= commandLine.Length(); i++) { if ((commandLine[i] == ' ' && !quoted && commandLine[i - 1] != '\\') || i == commandLine.Length()) { if (!param.Length()) continue; if (first) command = param; else args.Add(param); first = False; param = NIL; j = 0; } else if (commandLine[i] == '\"') { quoted = !quoted; } else if (!(commandLine[i] == '\\' && commandLine[i + 1] == ' ')) { param[j++] = commandLine[i]; } } } S::ArgumentsParser::~ArgumentsParser() { } smooth-0.9.11~git20260403.0230c0da/classes/misc/array.cpp000066400000000000000000000104261516402577000221750ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::IndexArray::IndexArray() { nOfEntries = 0; greatestIndex = 0; sorted = True; lastAccessedEntry = 0; lockingEnabled = False; lock = NIL; } S::IndexArray::~IndexArray() { if (lock != NIL) { delete lock; lock = NIL; } } S::Bool S::IndexArray::InsertAtPos(Int position, Int index) { WriteLock lock(*this); if (position > nOfEntries || position < 0) return False; if (!IndexAvailable(index)) return False; if (greatestIndex < index) greatestIndex = index; if (indices.Size() == nOfEntries) indices.Resize(8 > nOfEntries * 1.25 ? 8 : nOfEntries * 1.25); memmove(indices + position + 1, indices + position, (nOfEntries - position) * sizeof(Int)); indices[position] = index; nOfEntries++; if ((position >= 1 && indices[position - 1] > index) || (position < nOfEntries - 1 && indices[position + 1] < index)) sorted = False; return True; } S::Bool S::IndexArray::Move(Int index1, Int index2) { WriteLock lock(*this); if (index1 > greatestIndex || index2 > greatestIndex) return False; return MoveNth(GetEntryNumberByIndex(index1), GetEntryNumberByIndex(index2)); } S::Bool S::IndexArray::MoveNth(Int n, Int m) { WriteLock lock(*this); if (nOfEntries <= n || n < 0 || nOfEntries <= m || m < 0) return False; Int backupIndex = indices[n]; if (m < n) memmove(indices + m + 1, indices + m, (n - m) * sizeof(Int)); else memmove(indices + n, indices + n + 1, (m - n) * sizeof(Int)); indices[m] = backupIndex; sorted = False; return True; } S::Bool S::IndexArray::Remove(Int index) { WriteLock lock(*this); if (index > greatestIndex) return False; return RemoveNth(GetEntryNumberByIndex(index)); } S::Bool S::IndexArray::RemoveNth(Int n) { WriteLock lock(*this); if (nOfEntries <= n || n < 0) return False; if (nOfEntries == 1) return RemoveAll(); memmove(indices + n, indices + n + 1, (nOfEntries - n - 1) * sizeof(Int)); nOfEntries--; return True; } S::Bool S::IndexArray::RemoveAll() { WriteLock lock(*this); if (nOfEntries == 0) return True; indices.Free(); nOfEntries = 0; greatestIndex = 0; sorted = True; lastAccessedEntry = 0; return True; } S::Int S::IndexArray::GetNthIndex(Int n) const { ReadLock lock(*this); if (nOfEntries > n && n >= 0) return indices[n]; return -1; } S::Bool S::IndexArray::EnableLocking() const { lockingEnabled = True; if (lock == NIL) lock = new Threads::RWLock(); return True; } S::Bool S::IndexArray::DisableLocking() const { lockingEnabled = False; return True; } S::Bool S::IndexArray::IndexAvailable(Int index) const { ReadLock lock(*this); if (index > greatestIndex) return True; if (GetEntryNumberByIndex(index) == -1) return True; else return False; } S::Int S::IndexArray::GetEntryNumberByIndex(Int index) const { ReadLock lock(*this); if (nOfEntries == 0) return -1; Int entryNumber = -1; Int lastAccessed = lastAccessedEntry; /* Check entries around last accessed entry. */ if (lastAccessed < nOfEntries && indices[lastAccessed ] == index) entryNumber = lastAccessed; else if (lastAccessed > 0 && lastAccessed <= nOfEntries && indices[lastAccessed - 1] == index) entryNumber = lastAccessed - 1; else if (lastAccessed + 1 < nOfEntries && indices[lastAccessed + 1] == index) entryNumber = lastAccessed + 1; /* Binary search for sorted lists. */ else if (sorted) { Int bottom = 0; Int top = nOfEntries - 1; while (top >= bottom) { Int i = (top + bottom) / 2; Int e = indices[i]; if (e == index) { entryNumber = i; break; } if (e < index) bottom = i + 1; else top = i - 1; } } /* Linear search otherwise. */ else { for (Int i = 0; i < nOfEntries; i++) { if (indices[i] == index) { entryNumber = i; break; } } } if (entryNumber >= 0) lastAccessedEntry = entryNumber; return entryNumber; } smooth-0.9.11~git20260403.0230c0da/classes/misc/binary.cpp000066400000000000000000000036411516402577000223440ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::Binary::Binary() { } S::Binary::Binary(const Binary &) { } S::Bool S::Binary::GetBit(Int n, UnsignedInt bit) { return IsFlagSet(n, (Int) Math::Pow(2l, (Signed) bit)); } S::Int S::Binary::SetBit(Int &n, UnsignedInt bit, Bool value) { if (value) return (n |= (Int) Math::Pow(2l, (Signed) bit)); else return (n = ((n | (Int) Math::Pow(2l, (Signed) bit)) ^ (Int) Math::Pow(2l, (Signed) bit))); } S::Int S::Binary::GetBits(Int n, UnsignedInt startBit, UnsignedInt endBit) { Int retVal = 0; if (startBit >= 32 || endBit >= 32) return -1; for (UnsignedInt i = startBit; i <= endBit; i++) { retVal += (Int) Math::Pow(2l, (Signed) i - (Signed) startBit) * ((n >> i) & 1); } return retVal; } S::Int S::Binary::SetBits(Int &n, UnsignedInt startBit, UnsignedInt endBit, Int value) { if (startBit >= 32 || endBit >= 32) return -1; for (UnsignedInt i = startBit; i <= endBit; i++) { SetBit(n, i, (value >> (i - startBit)) & 1); } return n; } S::Int S::Binary::And(Int a, Int b) { return a & b; } S::Int S::Binary::Or(Int a, Int b) { return a | b; } S::Int S::Binary::Xor(Int a, Int b) { return a ^ b; } S::Int S::Binary::Not(Int a) { return ~a; } S::Int S::Binary::ShiftL(Int n, Int s) { return n << s; } S::Int S::Binary::ShiftR(Int n, Int s) { return n >> s; } S::Bool S::Binary::IsFlagSet(Int n, Int flag) { return ((n & flag) == flag); } S::Int S::Binary::SetFlag(Int &n, Int flag) { return (n |= flag); } smooth-0.9.11~git20260403.0230c0da/classes/misc/config.cpp000066400000000000000000000236671516402577000223370ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include static const S::String ConfigurationDefaultID = "default"; static const S::String NodeConfigurationID = "configuration"; static const S::String NodeSectionID = "section"; static const S::String NodeValueID = "value"; static const S::String AttributeInheritingID = "inheriting"; static const S::String AttributeNameID = "name"; S::Configuration::Configuration() { ownRoot = NIL; configFile = NIL; activeConfig = ConfigurationDefaultID; } S::Configuration::Configuration(const String &file, Bool create) { ownRoot = NIL; configFile = NIL; activeConfig = ConfigurationDefaultID; Open(file, create); } S::Configuration::Configuration(const Configuration &oConfig) { ownRoot = NIL; configFile = new XML::Document(*oConfig.configFile); activeConfig = oConfig.activeConfig; } S::Configuration::~Configuration() { if (configFile != NIL) Close(); } S::Int S::Configuration::Open(const String &file, Bool create) { if (configFile != NIL) Close(); configFile = new XML::Document(); if (configFile->LoadFile(file) == Success()) { fileName = file; } else if (configFile->LoadFile(GUI::Application::GetStartupDirectory().Append(file)) == Success()) { fileName = GUI::Application::GetStartupDirectory().Append(file); } else if (configFile->LoadFile(GUI::Application::GetApplicationDirectory().Append(file)) == Success()) { fileName = GUI::Application::GetApplicationDirectory().Append(file); } else { if (!create) { Close(); return Error(); } else { ownRoot = new XML::Node("ConfigFile"); configFile->SetRootNode(ownRoot); ownRoot->AddNode(NodeConfigurationID)->SetAttribute(AttributeNameID, ConfigurationDefaultID); if (file[1] == ':' || file[0] == '/' || file[0] == '\\') fileName = file; else fileName = GUI::Application::GetApplicationDirectory().Append(file); } } /* Check XML file type. */ XML::Node *root = configFile->GetRootNode(); if (root == NIL || root->GetNodeByName(NodeConfigurationID) == NIL) { Close(); return Error(); } return Success(); } S::Int S::Configuration::Save() { if (configFile == NIL) return Error(); XML::Node *root = configFile->GetRootNode(); if (fileName != NIL && root != NIL) { /* Create base directory first. */ Directory(File(fileName).GetFilePath()).Create(); /* Save config file. */ XML::Node *configurationNode = root->GetNodeByName(NodeConfigurationID); if (configurationNode != NIL && configurationNode->GetNOfNodes() >= 1) configFile->SaveFile(fileName); } return Success(); } S::Int S::Configuration::Close() { if (configFile != NIL) { delete configFile; configFile = NIL; fileName = NIL; } if (ownRoot != NIL) { delete ownRoot; ownRoot = NIL; } return Success(); } S::Int S::Configuration::AddConfiguration(const String &nConfig) { if (configFile == NIL) return Error(); XML::Node *configuration = FindConfigurationNode(nConfig); if (configuration == NIL) { configFile->GetRootNode()->AddNode(NodeConfigurationID)->SetAttribute(AttributeNameID, nConfig); return Success(); } return Error(); } S::Int S::Configuration::RemoveConfiguration(const String &rConfig) { if (configFile == NIL) return Error(); XML::Node *configuration = FindConfigurationNode(rConfig); if (configuration != NIL) { if (activeConfig == rConfig) SetActiveConfiguration(ConfigurationDefaultID); configFile->GetRootNode()->RemoveNode(configuration); return Success(); } return Error(); } S::Int S::Configuration::GetNOfConfigurations() const { XML::Node *root = configFile->GetRootNode(); if (root == NIL) return 0; Int count = 0; for (Int i = 0; i < root->GetNOfNodes(); i++) { XML::Node *node = root->GetNthNode(i); if (node->GetName() != NodeConfigurationID) continue; count++; } return count; } S::String S::Configuration::GetNthConfigurationName(Int n) const { XML::Node *root = configFile->GetRootNode(); if (root == NIL) return NIL; Int count = 0; for (Int i = 0; i < root->GetNOfNodes(); i++) { XML::Node *node = root->GetNthNode(i); if (node->GetName() != NodeConfigurationID) continue; if (count++ == n) { XML::Attribute *attributeName = node->GetAttributeByName(AttributeNameID); if (attributeName != NIL) return attributeName->GetContent(); else return NIL; } } return NIL; } S::Int S::Configuration::SetActiveConfiguration(const String &nConfig) { if (configFile == NIL) return Error(); XML::Node *configuration = FindConfigurationNode(nConfig); if (configuration == NIL) AddConfiguration(nConfig); activeConfig = nConfig; return Success(); } S::Int S::Configuration::SetParentConfiguration(const String &nParent) { if (configFile == NIL) return Error(); XML::Node *configuration = FindConfigurationNode(activeConfig); if (configuration == NIL) return Error(); configuration->SetAttribute(AttributeInheritingID, nParent); return Success(); } S::String S::Configuration::GetConfigurationName() const { if (configFile == NIL) return NIL; XML::Node *configuration = FindConfigurationNode(activeConfig); if (configuration == NIL) return NIL; return activeConfig; } S::Int S::Configuration::SetConfigurationName(const String &nName) { if (configFile == NIL) return Error(); XML::Node *configuration = FindConfigurationNode(activeConfig); if (configuration == NIL) return Error(); activeConfig = nName; configuration->SetAttribute(AttributeNameID, nName); return Success(); } S::Int S::Configuration::GetIntValue(const String §ion, const String &name, Int defValue) { if (configFile == NIL) return defValue; XML::Node *value = FindValueNode(section, name); if (value != NIL) { return value->GetContent().ToInt(); } else { XML::Node *configuration = FindConfigurationNode(activeConfig); XML::Attribute *attributeInheriting = configuration->GetAttributeByName(AttributeInheritingID); if (attributeInheriting != NIL) { String oConfig = activeConfig; activeConfig = attributeInheriting->GetContent(); Int retVal = GetIntValue(section, name, defValue); activeConfig = oConfig; return retVal; } return defValue; } } S::Int S::Configuration::SetIntValue(const String §ion, const String &name, Int newValue) { if (configFile == NIL) return Error(); XML::Node *valueNode = FindValueNode(section, name); if (valueNode != NIL) { valueNode->SetContent(String::FromInt(newValue)); } else { XML::Node *sectionNode = FindSectionNode(section); if (sectionNode == NIL) { sectionNode = FindConfigurationNode(activeConfig)->AddNode(NodeSectionID); sectionNode->SetAttribute(AttributeNameID, section); } valueNode = sectionNode->AddNode(NodeValueID, String::FromInt(newValue)); valueNode->SetAttribute(AttributeNameID, name); } return Success(); } S::String S::Configuration::GetStringValue(const String §ion, const String &name, const String &defValue) { if (configFile == NIL) return defValue; XML::Node *value = FindValueNode(section, name); if (value != NIL) { return value->GetContent(); } else { XML::Node *configuration = FindConfigurationNode(activeConfig); XML::Attribute *attributeInheriting = configuration->GetAttributeByName(AttributeInheritingID); if (attributeInheriting != NIL) { String oConfig = activeConfig; activeConfig = attributeInheriting->GetContent(); String retVal = GetStringValue(section, name, defValue); activeConfig = oConfig; return retVal; } return defValue; } } S::Int S::Configuration::SetStringValue(const String §ion, const String &name, const String &newValue) { if (configFile == NIL) return Error(); XML::Node *valueNode = FindValueNode(section, name); if (valueNode != NIL) { valueNode->SetContent(newValue); } else { XML::Node *sectionNode = FindSectionNode(section); if (sectionNode == NIL) { sectionNode = FindConfigurationNode(activeConfig)->AddNode(NodeSectionID); sectionNode->SetAttribute(AttributeNameID, section); } valueNode = sectionNode->AddNode(NodeValueID, newValue); valueNode->SetAttribute(AttributeNameID, name); } return Success(); } S::XML::Node *S::Configuration::FindConfigurationNode(const String &configuration) const { XML::Node *root = configFile->GetRootNode(); if (root == NIL) return NIL; for (Int i = 0; i < root->GetNOfNodes(); i++) { XML::Node *node = root->GetNthNode(i); if (node->GetName() != NodeConfigurationID) continue; XML::Attribute *attributeName = node->GetAttributeByName(AttributeNameID); if (attributeName != NIL && attributeName->GetContent() == configuration) return node; } return NIL; } S::XML::Node *S::Configuration::FindSectionNode(const String §ion) const { XML::Node *configuration = FindConfigurationNode(activeConfig); if (configuration == NIL) return NIL; for (Int i = 0; i < configuration->GetNOfNodes(); i++) { XML::Node *node = configuration->GetNthNode(i); XML::Attribute *attributeName = node->GetAttributeByName(AttributeNameID); if (attributeName != NIL && attributeName->GetContent() == section) return node; } return NIL; } S::XML::Node *S::Configuration::FindValueNode(const String §, const String &name) const { XML::Node *section = FindSectionNode(sect); if (section == NIL) return NIL; for (Int i = 0; i < section->GetNOfNodes(); i++) { XML::Node *node = section->GetNthNode(i); XML::Attribute *attributeName = node->GetAttributeByName(AttributeNameID); if (attributeName != NIL && attributeName->GetContent() == name) return node; } return NIL; } smooth-0.9.11~git20260403.0230c0da/classes/misc/datetime.cpp000066400000000000000000000100741516402577000226520ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #ifdef __WIN32__ # define time_t __time64_t # define time _time64 # define mktime _mktime64 #endif static tm localtime_p(time_t *time) { tm lt; memset(<, 0, sizeof(tm)); #ifdef __WIN32__ tm *ltp = _localtime64(time); if (ltp != NULL) lt = *ltp; #else localtime_r(time, <); #endif return lt; } S::DateTime::DateTime(Void *iTime) { value = new time_t; if (iTime != NIL) memcpy(value, iTime, sizeof(time_t)); else memset(value, 0, sizeof(time_t)); } S::DateTime::DateTime(const DateTime &iDateTime) { value = new time_t; *this = iDateTime; } S::DateTime::~DateTime() { delete (time_t *) value; } S::DateTime S::DateTime::Current() { time_t t = time(NIL); return DateTime(&t); } S::DateTime &S::DateTime::operator =(const DateTime &newDateTime) { if (&newDateTime == this) return *this; memcpy(value, newDateTime.value, sizeof(time_t)); return *this; } S::Bool S::DateTime::SetYMD(Int year, Int month, Int day) { if (year < 1900 ) return False; if (month <= 0 || month > 12) return False; if (day <= 0 || day > 31) return False; tm lt = localtime_p((time_t *) value); lt.tm_year = year - 1900; lt.tm_mon = month - 1; lt.tm_mday = day; time_t t = mktime(<); memcpy(value, &t, sizeof(time_t)); return True; } S::Bool S::DateTime::SetHMS(Int hour, Int min, Int sec) { if (hour < 0 || hour >= 24) return False; if (min < 0 || min >= 60) return False; if (sec < 0 || sec >= 60) return False; tm lt = localtime_p((time_t *) value); lt.tm_hour = hour; lt.tm_min = min; lt.tm_sec = sec; time_t t = mktime(<); memcpy(value, &t, sizeof(time_t)); return True; } S::Int S::DateTime::GetYear() const { tm lt = localtime_p((time_t *) value); return lt.tm_year + 1900; } S::Int S::DateTime::GetMonth() const { tm lt = localtime_p((time_t *) value); return lt.tm_mon + 1; } S::Int S::DateTime::GetDay() const { tm lt = localtime_p((time_t *) value); return lt.tm_mday; } S::Bool S::DateTime::SetYear(Int year) { if (year < 0) return False; tm lt = localtime_p((time_t *) value); lt.tm_year = year - 1900; time_t t = mktime(<); memcpy(value, &t, sizeof(time_t)); return True; } S::Bool S::DateTime::SetMonth(Int month) { if (month <= 0 || month > 12) return False; tm lt = localtime_p((time_t *) value); lt.tm_mon = month - 1; time_t t = mktime(<); memcpy(value, &t, sizeof(time_t)); return True; } S::Bool S::DateTime::SetDay(Int day) { if (day <= 0 || day > 31) return False; tm lt = localtime_p((time_t *) value); lt.tm_mday = day; time_t t = mktime(<); memcpy(value, &t, sizeof(time_t)); return True; } S::Int S::DateTime::GetHour() const { tm lt = localtime_p((time_t *) value); return lt.tm_hour; } S::Int S::DateTime::GetMinute() const { tm lt = localtime_p((time_t *) value); return lt.tm_min; } S::Int S::DateTime::GetSecond() const { tm lt = localtime_p((time_t *) value); return lt.tm_sec; } S::Bool S::DateTime::SetHour(Int hour) { if (hour < 0 || hour >= 24) return False; tm lt = localtime_p((time_t *) value); lt.tm_hour = hour; time_t t = mktime(<); memcpy(value, &t, sizeof(time_t)); return True; } S::Bool S::DateTime::SetMinute(Int min) { if (min < 0 || min >= 60) return False; tm lt = localtime_p((time_t *) value); lt.tm_min = min; time_t t = mktime(<); memcpy(value, &t, sizeof(time_t)); return True; } S::Bool S::DateTime::SetSecond(Int sec) { if (sec < 0 || sec >= 60) return False; tm lt = localtime_p((time_t *) value); lt.tm_sec = sec; time_t t = mktime(<); memcpy(value, &t, sizeof(time_t)); return True; } smooth-0.9.11~git20260403.0230c0da/classes/misc/encoding/000077500000000000000000000000001516402577000221365ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/misc/encoding/Makefile000066400000000000000000000006731516402577000236040ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = base64.o urlencode.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands # Optimize encoding functions for speed in release mode: ifeq ($(findstring release,$(config)),release) override CXXFLAGS += -O3 endif smooth-0.9.11~git20260403.0230c0da/classes/misc/encoding/base64.cpp000077500000000000000000000050721516402577000237350ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::Encoding::Base64::Base64(Buffer &iBuffer) : buffer(iBuffer) { } S::Encoding::Base64::~Base64() { } S::String S::Encoding::Base64::Encode(Int bytes) const { if (bytes > buffer.Size()) return NIL; if (bytes == -1) bytes = buffer.Size(); String b64; /* Set last byte to reserve memory and speed up processing. */ b64[(Int) Math::Ceil(bytes / 3.0) * 4] = 0; for (Int i = 0; i < bytes; i += 3) { Int val[4] = { 64, 64, 64, 64 }; val[0] = buffer[i + 0] >> 2; val[1] = ((buffer[i + 0] & 3) << 4) | (((bytes > i + 1) ? buffer[i + 1] : 0) >> 4); if (bytes > i + 1) val[2] = ((buffer[i + 1] & 15) << 2) | (((bytes > i + 2) ? buffer[i + 2] : 0) >> 6); if (bytes > i + 2) val[3] = buffer[i + 2] & 63; for (Int j = 0; j < 4; j++) { if (val[j] >= 0 && val[j] <= 25) b64[i / 3 * 4 + j] = 'A' + val[j] - 0; else if (val[j] >= 26 && val[j] <= 51) b64[i / 3 * 4 + j] = 'a' + val[j] - 26; else if (val[j] >= 52 && val[j] <= 61) b64[i / 3 * 4 + j] = '0' + val[j] - 52; else if (val[j] == 62) b64[i / 3 * 4 + j] = '+'; else if (val[j] == 63) b64[i / 3 * 4 + j] = '/'; else if (val[j] == 64) b64[i / 3 * 4 + j] = '='; } } return b64; } S::Int S::Encoding::Base64::Decode(const String &string) { Int bytes = 0; Int length = string.Length(); buffer.Resize(length / 4 * 3 + 1); for (Int i = 0; i < length; i += 4) { Int val[4] = { 64, 64, 64, 64 }; for (Int j = 0; j < 4; j++) { wchar_t value = string[i + j]; if (value >= 'A' && value <= 'Z') val[j] = value - 'A' + 0; else if (value >= 'a' && value <= 'z') val[j] = value - 'a' + 26; else if (value >= '0' && value <= '9') val[j] = value - '0' + 52; else if (value == '+') val[j] = 62; else if (value == '/') val[j] = 63; } if (val[0] == 64) break; if (val[1] != 64) buffer[bytes++] = ( val[0] << 2) | (val[1] >> 4); if (val[2] != 64) buffer[bytes++] = ((val[1] & 15) << 4) | (val[2] >> 2); if (val[3] != 64) buffer[bytes++] = ((val[2] & 3) << 6) | (val[3]); buffer[bytes] = 0; } return bytes; } smooth-0.9.11~git20260403.0230c0da/classes/misc/encoding/urlencode.cpp000066400000000000000000000041061516402577000246230ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::String S::Encoding::URLEncode::Encode(const String &string, Bool encodeReserved) { /* Convert input string to UTF-8. */ String utf8; utf8.ImportFrom("ISO-8859-1", string.ConvertTo("UTF-8")); /* Encode UTF-8 string using URL encode. */ String encoded; Int length = utf8.Length(); for (Int i = 0, e = 0; i < length; i++) { wchar_t value = utf8[i]; if ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z') || (value >= '0' && value <= '9') || (value == '-' || value == '_' || value == '.' || value == '~') || (!encodeReserved && (value == '!' || value == '*' || value == '\'' || value == '(' || value == ')' || value == ';' || value == ':' || value == '@' || value == '&' || value == '=' || value == '+' || value == '$' || value == ',' || value == '/' || value == '?' || value == '#' || value == '[' || value == ']'))) { encoded[e++] = value; } else { String hex = Number((Int64) value).ToHexString(2).ToUpper(); encoded[e++] = '%'; encoded[e++] = hex[0]; encoded[e++] = hex[1]; } } return encoded; } S::String S::Encoding::URLEncode::Decode(const String &encoded) { /* Decode URL encoded string to UTF-8. */ String utf8; Int length = encoded.Length(); for (Int i = 0, d = 0; i < length; i++) { if (encoded[i] == '%') { utf8[d++] = (Int64) Number::FromHexString(encoded.SubString(i + 1, 2)); i += 2; } else { utf8[d++] = encoded[i]; } } /* Import string from UTF-8. */ String string; string.ImportFrom("UTF-8", utf8.ConvertTo("ISO-8859-1")); return string; } smooth-0.9.11~git20260403.0230c0da/classes/misc/hash/000077500000000000000000000000001516402577000212735ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/misc/hash/Makefile000066400000000000000000000007071516402577000227370ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = crc16.o crc32.o crc64.o md5.o sha1.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands # Optimize hash functions for speed in release mode: ifeq ($(findstring release,$(config)),release) override CXXFLAGS += -O3 endif smooth-0.9.11~git20260403.0230c0da/classes/misc/hash/crc16.cpp000066400000000000000000000043051516402577000227170ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::UnsignedInt16 S::Hash::CRC16::table[8][256]; S::Bool S::Hash::CRC16::initialized = InitTable(); S::Hash::CRC16::CRC16() { Reset(); } S::Hash::CRC16::~CRC16() { } S::Bool S::Hash::CRC16::InitTable() { UnsignedInt16 polynomial = 0x8005; for (Int i = 0; i <= 0xFF; i++) { UnsignedInt16 value = Reflect(i, 8) << 8; for (Int j = 0; j < 8; j++) value = (value << 1) ^ (value & (1 << 15) ? polynomial : 0); table[0][i] = Reflect(value, 16); } for (Int i = 0; i <= 0xFF; i++) { for (Int j = 1; j < 8; j++) table[j][i] = table[0][table[j - 1][i] & 0xFF] ^ (table[j - 1][i] >> 8); } return True; } S::UnsignedInt16 S::Hash::CRC16::Reflect(UnsignedInt16 ref, char ch) { UnsignedInt16 value(0); for (Int i = 1; i < (ch + 1); i++) { if (ref & 1) value |= 1 << (ch - i); ref >>= 1; } return value; } S::Bool S::Hash::CRC16::Reset() { crc = 0x0000; return True; } S::Bool S::Hash::CRC16::Feed(const UnsignedByte *data, Int size) { while (size >= 8) { crc ^= data[1] << 8 | data[0]; crc = table[7][crc & 0xFF] ^ table[6][crc >> 8] ^ table[5][data[2] ] ^ table[4][data[3] ] ^ table[3][data[4] ] ^ table[2][data[5] ] ^ table[1][data[6] ] ^ table[0][data[7] ]; data += 8; size -= 8; } while (size--) crc = (crc >> 8) ^ table[0][(crc & 0xFF) ^ *data++]; return True; } S::Bool S::Hash::CRC16::Feed(const Buffer &data) { return Feed(data, data.Size()); } S::UnsignedInt16 S::Hash::CRC16::Finish() { return crc; } S::UnsignedInt16 S::Hash::CRC16::Compute(const UnsignedByte *data, Int size) { CRC16 crc16; crc16.Feed(data, size); return crc16.Finish(); } S::UnsignedInt16 S::Hash::CRC16::Compute(const Buffer &data) { return Compute(data, data.Size()); } smooth-0.9.11~git20260403.0230c0da/classes/misc/hash/crc32.cpp000077500000000000000000000044401516402577000227200ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::UnsignedInt32 S::Hash::CRC32::table[8][256]; S::Bool S::Hash::CRC32::initialized = InitTable(); S::Hash::CRC32::CRC32() { Reset(); } S::Hash::CRC32::~CRC32() { } S::Bool S::Hash::CRC32::InitTable() { UnsignedInt32 polynomial = 0x04C11DB7; for (Int i = 0; i <= 0xFF; i++) { UnsignedInt32 value = Reflect(i, 8) << 24; for (Int j = 0; j < 8; j++) value = (value << 1) ^ (value & (1 << 31) ? polynomial : 0); table[0][i] = Reflect(value, 32); } for (Int i = 0; i <= 0xFF; i++) { for (Int j = 1; j < 8; j++) table[j][i] = table[0][table[j - 1][i] & 0xFF] ^ (table[j - 1][i] >> 8); } return True; } S::UnsignedInt32 S::Hash::CRC32::Reflect(UnsignedInt32 ref, char ch) { UnsignedInt32 value(0); for (Int i = 1; i < (ch + 1); i++) { if (ref & 1) value |= 1 << (ch - i); ref >>= 1; } return value; } S::Bool S::Hash::CRC32::Reset() { crc = 0xFFFFFFFF; return True; } S::Bool S::Hash::CRC32::Feed(const UnsignedByte *data, Int size) { while (size >= 8) { crc ^= data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]; crc = table[7][ crc & 0xFF] ^ table[6][(crc >> 8) & 0xFF] ^ table[5][(crc >> 16) & 0xFF] ^ table[4][ crc >> 24 ] ^ table[3][data[4] ] ^ table[2][data[5] ] ^ table[1][data[6] ] ^ table[0][data[7] ]; data += 8; size -= 8; } while (size--) crc = (crc >> 8) ^ table[0][(crc & 0xFF) ^ *data++]; return True; } S::Bool S::Hash::CRC32::Feed(const Buffer &data) { return Feed(data, data.Size()); } S::UnsignedInt32 S::Hash::CRC32::Finish() { return crc ^ 0xFFFFFFFF; } S::UnsignedInt32 S::Hash::CRC32::Compute(const UnsignedByte *data, Int size) { CRC32 crc32; crc32.Feed(data, size); return crc32.Finish(); } S::UnsignedInt32 S::Hash::CRC32::Compute(const Buffer &data) { return Compute(data, data.Size()); } smooth-0.9.11~git20260403.0230c0da/classes/misc/hash/crc64.cpp000066400000000000000000000041721516402577000227240ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::UnsignedInt64 S::Hash::CRC64::table[8][256]; S::Bool S::Hash::CRC64::initialized = InitTable(); S::Hash::CRC64::CRC64() { Reset(); } S::Hash::CRC64::~CRC64() { } S::Bool S::Hash::CRC64::InitTable() { UnsignedInt64 polynomial = 0x95AC9329AC4BC9B5ULL; for (Int i = 0; i <= 0xFF; i++) { UnsignedInt64 value = i; for (Int j = 0; j < 8; j++) value = (value >> 1) ^ (value & 1 ? polynomial : 0); table[0][i] = value; } for (Int i = 0; i <= 0xFF; i++) { for (Int j = 1; j < 8; j++) table[j][i] = table[0][table[j - 1][i] & 0xFF] ^ (table[j - 1][i] >> 8); } return True; } S::Bool S::Hash::CRC64::Reset() { crc = 0xFFFFFFFFFFFFFFFFULL; return True; } S::Bool S::Hash::CRC64::Feed(const UnsignedByte *data, Int size) { while (size >= 8) { crc = table[7][data[0] ^ ( crc & 0xFF)] ^ table[6][data[1] ^ ((crc >> 8) & 0xFF)] ^ table[5][data[2] ^ ((crc >> 16) & 0xFF)] ^ table[4][data[3] ^ ((crc >> 24) & 0xFF)] ^ table[3][data[4] ^ ((crc >> 32) & 0xFF)] ^ table[2][data[5] ^ ((crc >> 40) & 0xFF)] ^ table[1][data[6] ^ ((crc >> 48) & 0xFF)] ^ table[0][data[7] ^ (crc >> 56) ]; data += 8; size -= 8; } while (size--) crc = (crc >> 8) ^ table[0][(crc & 0xFF) ^ *data++]; return True; } S::Bool S::Hash::CRC64::Feed(const Buffer &data) { return Feed(data, data.Size()); } S::UnsignedInt64 S::Hash::CRC64::Finish() { return crc ^ 0xFFFFFFFFFFFFFFFFULL; } S::UnsignedInt64 S::Hash::CRC64::Compute(const UnsignedByte *data, Int size) { CRC64 crc64; crc64.Feed(data, size); return crc64.Finish(); } S::UnsignedInt64 S::Hash::CRC64::Compute(const Buffer &data) { return Compute(data, data.Size()); } smooth-0.9.11~git20260403.0230c0da/classes/misc/hash/md5.cpp000077500000000000000000000213741516402577000224760ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* This code is derived from the RSA Data Security, * Inc. MD5 Message-Digest Algorithm. */ #include #include /* Constants for MD5Transform routine. */ const S::Int S11 = 7, S12 = 12, S13 = 17, S14 = 22, S21 = 5, S22 = 9, S23 = 14, S24 = 20, S31 = 4, S32 = 11, S33 = 16, S34 = 23, S41 = 6, S42 = 10, S43 = 15, S44 = 21; /* MD5 padding bytes. */ static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* F, G, H and I are basic MD5 functions. */ #define F(x, y, z) (((x) & (y)) | ((~x) & ( z))) #define G(x, y, z) (((x) & (z)) | (( y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) \ { \ (a) += F((b), (c), (d)) + (x) + (UnsignedInt32) (ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) \ { \ (a) += G((b), (c), (d)) + (x) + (UnsignedInt32) (ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) \ { \ (a) += H((b), (c), (d)) + (x) + (UnsignedInt32) (ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) \ { \ (a) += I((b), (c), (d)) + (x) + (UnsignedInt32) (ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } /* GET_INT32 reads an integer from a buffer. */ #define GET_INT32(x, b) ((b)[4 * (x) ] | \ (b)[4 * (x) + 1] << 8 | \ (b)[4 * (x) + 2] << 16 | \ (b)[4 * (x) + 3] << 24) /* REVERSE_INT32 changes the byte order of an integer. */ #define REVERSE_INT32(x) ((( (x) & 0xFF) << 24) | \ ((((x) >> 8) & 0xFF) << 16) | \ ((((x) >> 16) & 0xFF) << 8) | \ (((x) >> 24) & 0xFF) ) S::Hash::MD5::MD5() { Reset(); } S::Hash::MD5::~MD5() { } S::Void S::Hash::MD5::Transform(UnsignedByte *data) { UnsignedInt32 a = state[0]; UnsignedInt32 b = state[1]; UnsignedInt32 c = state[2]; UnsignedInt32 d = state[3]; /* Round 1 */ FF(a, b, c, d, GET_INT32( 0, data), S11, 0xd76aa478); /* 1 */ FF(d, a, b, c, GET_INT32( 1, data), S12, 0xe8c7b756); /* 2 */ FF(c, d, a, b, GET_INT32( 2, data), S13, 0x242070db); /* 3 */ FF(b, c, d, a, GET_INT32( 3, data), S14, 0xc1bdceee); /* 4 */ FF(a, b, c, d, GET_INT32( 4, data), S11, 0xf57c0faf); /* 5 */ FF(d, a, b, c, GET_INT32( 5, data), S12, 0x4787c62a); /* 6 */ FF(c, d, a, b, GET_INT32( 6, data), S13, 0xa8304613); /* 7 */ FF(b, c, d, a, GET_INT32( 7, data), S14, 0xfd469501); /* 8 */ FF(a, b, c, d, GET_INT32( 8, data), S11, 0x698098d8); /* 9 */ FF(d, a, b, c, GET_INT32( 9, data), S12, 0x8b44f7af); /* 10 */ FF(c, d, a, b, GET_INT32(10, data), S13, 0xffff5bb1); /* 11 */ FF(b, c, d, a, GET_INT32(11, data), S14, 0x895cd7be); /* 12 */ FF(a, b, c, d, GET_INT32(12, data), S11, 0x6b901122); /* 13 */ FF(d, a, b, c, GET_INT32(13, data), S12, 0xfd987193); /* 14 */ FF(c, d, a, b, GET_INT32(14, data), S13, 0xa679438e); /* 15 */ FF(b, c, d, a, GET_INT32(15, data), S14, 0x49b40821); /* 16 */ /* Round 2 */ GG(a, b, c, d, GET_INT32( 1, data), S21, 0xf61e2562); /* 17 */ GG(d, a, b, c, GET_INT32( 6, data), S22, 0xc040b340); /* 18 */ GG(c, d, a, b, GET_INT32(11, data), S23, 0x265e5a51); /* 19 */ GG(b, c, d, a, GET_INT32( 0, data), S24, 0xe9b6c7aa); /* 20 */ GG(a, b, c, d, GET_INT32( 5, data), S21, 0xd62f105d); /* 21 */ GG(d, a, b, c, GET_INT32(10, data), S22, 0x02441453); /* 22 */ GG(c, d, a, b, GET_INT32(15, data), S23, 0xd8a1e681); /* 23 */ GG(b, c, d, a, GET_INT32( 4, data), S24, 0xe7d3fbc8); /* 24 */ GG(a, b, c, d, GET_INT32( 9, data), S21, 0x21e1cde6); /* 25 */ GG(d, a, b, c, GET_INT32(14, data), S22, 0xc33707d6); /* 26 */ GG(c, d, a, b, GET_INT32( 3, data), S23, 0xf4d50d87); /* 27 */ GG(b, c, d, a, GET_INT32( 8, data), S24, 0x455a14ed); /* 28 */ GG(a, b, c, d, GET_INT32(13, data), S21, 0xa9e3e905); /* 29 */ GG(d, a, b, c, GET_INT32( 2, data), S22, 0xfcefa3f8); /* 30 */ GG(c, d, a, b, GET_INT32( 7, data), S23, 0x676f02d9); /* 31 */ GG(b, c, d, a, GET_INT32(12, data), S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH(a, b, c, d, GET_INT32( 5, data), S31, 0xfffa3942); /* 33 */ HH(d, a, b, c, GET_INT32( 8, data), S32, 0x8771f681); /* 34 */ HH(c, d, a, b, GET_INT32(11, data), S33, 0x6d9d6122); /* 35 */ HH(b, c, d, a, GET_INT32(14, data), S34, 0xfde5380c); /* 36 */ HH(a, b, c, d, GET_INT32( 1, data), S31, 0xa4beea44); /* 37 */ HH(d, a, b, c, GET_INT32( 4, data), S32, 0x4bdecfa9); /* 38 */ HH(c, d, a, b, GET_INT32( 7, data), S33, 0xf6bb4b60); /* 39 */ HH(b, c, d, a, GET_INT32(10, data), S34, 0xbebfbc70); /* 40 */ HH(a, b, c, d, GET_INT32(13, data), S31, 0x289b7ec6); /* 41 */ HH(d, a, b, c, GET_INT32( 0, data), S32, 0xeaa127fa); /* 42 */ HH(c, d, a, b, GET_INT32( 3, data), S33, 0xd4ef3085); /* 43 */ HH(b, c, d, a, GET_INT32( 6, data), S34, 0x04881d05); /* 44 */ HH(a, b, c, d, GET_INT32( 9, data), S31, 0xd9d4d039); /* 45 */ HH(d, a, b, c, GET_INT32(12, data), S32, 0xe6db99e5); /* 46 */ HH(c, d, a, b, GET_INT32(15, data), S33, 0x1fa27cf8); /* 47 */ HH(b, c, d, a, GET_INT32( 2, data), S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II(a, b, c, d, GET_INT32( 0, data), S41, 0xf4292244); /* 49 */ II(d, a, b, c, GET_INT32( 7, data), S42, 0x432aff97); /* 50 */ II(c, d, a, b, GET_INT32(14, data), S43, 0xab9423a7); /* 51 */ II(b, c, d, a, GET_INT32( 5, data), S44, 0xfc93a039); /* 52 */ II(a, b, c, d, GET_INT32(12, data), S41, 0x655b59c3); /* 53 */ II(d, a, b, c, GET_INT32( 3, data), S42, 0x8f0ccc92); /* 54 */ II(c, d, a, b, GET_INT32(10, data), S43, 0xffeff47d); /* 55 */ II(b, c, d, a, GET_INT32( 1, data), S44, 0x85845dd1); /* 56 */ II(a, b, c, d, GET_INT32( 8, data), S41, 0x6fa87e4f); /* 57 */ II(d, a, b, c, GET_INT32(15, data), S42, 0xfe2ce6e0); /* 58 */ II(c, d, a, b, GET_INT32( 6, data), S43, 0xa3014314); /* 59 */ II(b, c, d, a, GET_INT32(13, data), S44, 0x4e0811a1); /* 60 */ II(a, b, c, d, GET_INT32( 4, data), S41, 0xf7537e82); /* 61 */ II(d, a, b, c, GET_INT32(11, data), S42, 0xbd3af235); /* 62 */ II(c, d, a, b, GET_INT32( 2, data), S43, 0x2ad7d2bb); /* 63 */ II(b, c, d, a, GET_INT32( 9, data), S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; size += 64; } S::Bool S::Hash::MD5::Reset() { /* Load magic initialization constants. */ state[0] = 0x67452301; state[1] = 0xefcdab89; state[2] = 0x98badcfe; state[3] = 0x10325476; size = 0; return True; } S::Bool S::Hash::MD5::Feed(const UnsignedByte *data, Int size) { buffer.Resize(buffer.Size() + size); memcpy(buffer + buffer.Size() - size, data, size); for (Int i = 0; i + 63 < buffer.Size(); i += 64) Transform(buffer + i); memcpy(buffer, buffer + buffer.Size() - buffer.Size() % 64, buffer.Size() % 64); buffer.Resize(buffer.Size() % 64); return True; } S::Bool S::Hash::MD5::Feed(const Buffer &data) { return Feed(data, data.Size()); } S::String S::Hash::MD5::Finish() { UnsignedInt64 bits = (buffer.Size() + size) * 8; Int index = buffer.Size(); /* Pad out to 56 mod 64. */ Int padLen = (index < 56) ? (56 - index) : (120 - index); UnsignedByte *end = new UnsignedByte [128]; memcpy(end, buffer, index); memcpy(end + index, PADDING, padLen); end[index + padLen ] = bits & 0xFF; end[index + padLen + 1] = bits >> 8 & 0xFF; end[index + padLen + 2] = bits >> 16 & 0xFF; end[index + padLen + 3] = bits >> 24 & 0xFF; end[index + padLen + 4] = bits >> 32 & 0xFF; end[index + padLen + 5] = bits >> 40 & 0xFF; end[index + padLen + 6] = bits >> 48 & 0xFF; end[index + padLen + 7] = bits >> 56 & 0xFF; Transform(end); if (padLen > 56) Transform(end + 64); delete [] end; String string; for (Int i = 0; i < 4; i++) string.Append(Number((Int64) REVERSE_INT32(state[i])).ToHexString(8)); return string; } S::String S::Hash::MD5::Compute(const UnsignedByte *data, Int size) { MD5 md5; md5.Feed(data, size); return md5.Finish(); } S::String S::Hash::MD5::Compute(const Buffer &data) { return Compute(data, data.Size()); } smooth-0.9.11~git20260403.0230c0da/classes/misc/hash/sha1.cpp000077500000000000000000000070361516402577000226440ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2018 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include /* SHA-1 padding bytes. */ static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) S::Hash::SHA1::SHA1() { Reset(); } S::Hash::SHA1::~SHA1() { } S::Void S::Hash::SHA1::Transform(UnsignedByte *buffer) { UnsignedInt32 word[80]; for (Int j = 0; j < 16; j++) word[j] = buffer[j * 4 + 0] * 0x1000000 + buffer[j * 4 + 1] * 0x10000 + buffer[j * 4 + 2] * 0x100 + buffer[j * 4 + 3]; for (Int j = 16; j < 80; j++) word[j] = ROTATE_LEFT((word[j - 3] ^ word[j - 8] ^ word[j - 14] ^ word[j - 16]), 1); UnsignedInt32 a = state[0]; UnsignedInt32 b = state[1]; UnsignedInt32 c = state[2]; UnsignedInt32 d = state[3]; UnsignedInt32 e = state[4]; for (int m = 0; m < 80; m++) { UnsignedInt32 f = 0; UnsignedInt32 k = 0; if (m <= 19) { f = (b & c) | ((~b) & d); k = 0x5a827999; } else if (m <= 39) { f = b ^ c ^ d; k = 0x6ed9eba1; } else if (m <= 59) { f = (b & c) | (b & d) | (c & d); k = 0x8f1bbcdc; } else { f = b ^ c ^ d; k = 0xca62c1d6; } UnsignedInt32 temp = (ROTATE_LEFT(a, 5) + f + e + k + word[m]) & 0xFFFFFFFF; e = d; d = c; c = ROTATE_LEFT(b, 30); b = a; a = temp; } state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; size += 64; } S::Bool S::Hash::SHA1::Reset() { /* Load magic initialization constants. */ state[0] = 0x67452301; state[1] = 0xefcdab89; state[2] = 0x98badcfe; state[3] = 0x10325476; state[4] = 0xc3d2e1f0; size = 0; return True; } S::Bool S::Hash::SHA1::Feed(const UnsignedByte *data, Int size) { buffer.Resize(buffer.Size() + size); memcpy(buffer + buffer.Size() - size, data, size); for (Int i = 0; i + 63 < buffer.Size(); i += 64) Transform(buffer + i); memcpy(buffer, buffer + buffer.Size() - buffer.Size() % 64, buffer.Size() % 64); buffer.Resize(buffer.Size() % 64); return True; } S::Bool S::Hash::SHA1::Feed(const Buffer &data) { return Feed(data, data.Size()); } S::String S::Hash::SHA1::Finish() { UnsignedInt64 bits = (buffer.Size() + size) * 8; Int index = buffer.Size(); /* Pad out to 56 mod 64. */ Int padLen = (index < 56) ? (56 - index) : (120 - index); UnsignedByte *end = new UnsignedByte [128]; memcpy(end, buffer, index); memcpy(end + index, PADDING, padLen); for (Int i = 0; i < 8; i++) end[index + padLen + i] = bits >> 8 * (7 - i) & 0xFF; Transform(end); if (padLen > 56) Transform(end + 64); delete [] end; String string; for (Int i = 0; i < 5; i++) string.Append(Number((Int64) ((UnsignedInt32 *) state)[i]).ToHexString(8)); return string; } S::String S::Hash::SHA1::Compute(const UnsignedByte *data, Int size) { SHA1 sha1; sha1.Feed(data, size); return sha1.Finish(); } S::String S::Hash::SHA1::Compute(const Buffer &data) { return Compute(data, data.Size()); } smooth-0.9.11~git20260403.0230c0da/classes/misc/math.cpp000066400000000000000000000057121516402577000220120ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include namespace smooth { static Threads::Mutex randMutex; } const S::Float S::Math::Pi = 3.1415926535897932385; const S::Float S::Math::e = 2.7182818284590452354; S::Math::Math() { } S::Math::Math(const Math &) { } S::Float S::Math::Abs(Float f) { return fabs(f); } S::Float S::Math::Fract(Float f) { return f - Floor(f); } S::Int64 S::Math::Floor(Float f) { return (Int64) floor(f); } S::Int64 S::Math::Ceil(Float f) { return (Int64) ceil(f); } S::Float S::Math::Mod(Float fd, Float fb) { return fmod(fd, fb); } S::Float S::Math::Pow(Float fn, Float fe) { return pow(fn, fe); } S::Float S::Math::Sqrt(Float f) { return sqrt(f); } S::Float S::Math::Log(Float f) { return log(f); } S::Float S::Math::Log2(Float f) { return log(f) / log(2.0); } S::Float S::Math::Log10(Float f) { return log10(f); } S::Float S::Math::Exp(Float f) { return exp(f); } S::Float S::Math::Sin(Float f) { return sin(f); } S::Float S::Math::Cos(Float f) { return cos(f); } S::Float S::Math::Tan(Float f) { return tan(f); } S::Float S::Math::Sinh(Float f) { return sinh(f); } S::Float S::Math::Cosh(Float f) { return cosh(f); } S::Float S::Math::Tanh(Float f) { return tanh(f); } S::Float S::Math::Asin(Float f) { return asin(f); } S::Float S::Math::Acos(Float f) { return acos(f); } S::Float S::Math::Atan(Float f) { return atan(f); } S::Float S::Math::Atan2(Float fy, Float fx) { return atan2(fy, fx); } S::Float S::Math::Pow(Int in, Int ie) { Float value = 1; if (ie >= 0) for (Int i = 0; i < ie; i++) value *= in; else for (Int i = 0; i < -ie; i++) value /= in; return value; } S::Float S::Math::Pow(Int64 in, Int64 ie) { Float value = 1; if (ie >= 0) for (Int i = 0; i < ie; i++) value *= in; else for (Int i = 0; i < -ie; i++) value /= in; return value; } S::Void S::Math::RandomSeed() { Threads::Lock lock(randMutex); /* Seed the random number generator using a combination of the * current time, ticks since program start and the current thread ID. */ srand(time(NULL) ^ clock() ^ Threads::Thread::GetCurrentThreadID()); } S::Int32 S::Math::Random() { Threads::Lock lock(randMutex); /* rand() may generate only 15 bit numbers (e.g. on Windows), * so combine multiple results to generate a 32 bit value. */ Int32 value = 0; value = (rand() & 0xFFF) << 20; value |= (rand() & 0xFFF) << 8; value |= (rand() & 0xFF ) ; return value; } smooth-0.9.11~git20260403.0230c0da/classes/misc/memory.cpp000077500000000000000000000015361516402577000223740ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2017 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::Memory::Memory(Int size) { memory = (UnsignedByte *) malloc(size); } S::Memory::~Memory() { if (memory != NIL) free(memory); } S::Bool S::Memory::Resize(Int size) { UnsignedByte *oldMemory = memory; if ((memory = (UnsignedByte *) realloc(memory, size)) == NIL) { free(oldMemory); return False; } return True; } smooth-0.9.11~git20260403.0230c0da/classes/misc/number.cpp000077500000000000000000000144031516402577000223510ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include static const S::String kZero = "0"; static const S::String kMinus = "-"; static const S::String kPoint = "."; S::Number::Number(const Int64 iNumber) { intValue = iNumber; floatValue = iNumber; } S::Number::Number(const Float iNumber) { intValue = (Int64) iNumber; floatValue = iNumber; } S::Number::Number(const Number &iNumber) { *this = iNumber; } S::Number::~Number() { } S::Number::operator S::Int64 () const { return intValue; } S::Number::operator S::Float () const { return floatValue; } S::Number &S::Number::operator =(const Int64 number) { return *this = Number(number); } S::Number &S::Number::operator =(const Float number) { return *this = Number(number); } S::Number &S::Number::operator =(const Number &number) { intValue = number.intValue; floatValue = number.floatValue; return *this; } S::Bool S::Number::operator ==(const Int64 number) const { return *this == Number(number); } S::Bool S::Number::operator ==(const Float number) const { return *this == Number(number); } S::Bool S::Number::operator ==(const Number &number) const { if (intValue != number.intValue || floatValue != number.floatValue) return False; else return True; } S::Bool S::Number::operator !=(const Int64 number) const { return *this != Number(number); } S::Bool S::Number::operator !=(const Float number) const { return *this == Number(number); } S::Bool S::Number::operator !=(const Number &number) const { return !(*this == number); } S::Number S::Number::FromIntString(const String &string) { Int first = string[0]; Int sign = (first == '-' ? -1 : 1); Int skip = 0; if (first == '-' || first == '+') skip = 1; Int length = string.Length(); Int digits = 0; for (Int i = skip; i < length; i++) { Int digit = string[i]; if ((digit >= '0' && digit <= '9')) digits++; else break; } Int64 value = 0; for (Int i = 0; i < digits; i++) { value += Int64(string[skip + i] - '0') * (Int64) Math::Pow(10, digits - i - 1); } return value * sign; } S::Number S::Number::FromFloatString(const String &string) { Int first = string[0]; Int sign = (first == '-' ? -1 : 1); Int skip = 0; if (first == '-' || first == '+') skip = 1; Int length = string.Length(); Int digits = 0; for (Int i = skip; i < length; i++) { Int digit = string[i]; if ((digit >= '0' && digit <= '9')) digits++; else break; } Int digitsafp = 0; if (string[skip + digits] == '.') { for (Int i = skip + digits + 1; i < length; i++) { Int digit = string[i]; if ((digit >= '0' && digit <= '9')) digitsafp++; else break; } } Float value = Math::Abs(Int64(Number::FromIntString(string))); for (Int i = 0; i < digitsafp; i++) { value += Float(string[skip + digits + 1 + i] - '0') * Math::Pow(10, 0 - i - 1); } return value * sign; } S::Number S::Number::FromHexString(const String &string) { Int first = string[0]; Int second = string[1]; Int skip = 0; if (first == '0' && (second == 'x' || second == 'X')) skip = 2; Int length = string.Length(); Int digits = 0; for (Int i = skip; i < length; i++) { Int digit = string[i]; if ((digit >= '0' && digit <= '9') || (digit >= 'A' && digit <= 'F') || (digit >= 'a' && digit <= 'f')) digits++; else break; } Int64 value = 0; for (Int i = 0; i < digits; i++) { Int digit = string[skip + i]; if (digit >= '0' && digit <= '9') value += (Int64(digit - '0') << ((digits - i - 1) * 4)); else if (digit >= 'A' && digit <= 'F') value += (Int64(digit - 'A' + 10) << ((digits - i - 1) * 4)); else if (digit >= 'a' && digit <= 'f') value += (Int64(digit - 'a' + 10) << ((digits - i - 1) * 4)); } return value; } S::String S::Number::ToIntString() const { if (intValue == 0) return kZero; String string; Int length = (Int) Math::Log10(Math::Abs(intValue)) + 1; for (Int i = 0; i < length; i++) { string[i] = '0' + Int64(Math::Abs(intValue) / Math::Pow(10, length - i - 1)) % 10; } if (intValue < 0) string = String(kMinus).Append(string); return string; } S::String S::Number::ToFloatString() const { Int digits = 10; Int64 fract = (Int64) (Math::Fract(Math::Abs(floatValue)) * Math::Pow(10, digits)); Int lead = digits - Math::Floor((fract > 0 ? Math::Log10(fract) : -1) + 1.000000001); Int nOfNull = 0; for (Int i = 0; i < digits; i++) { if (Int64(fract / Math::Pow(10, i)) % 10 == 0) nOfNull++; else break; } Int nOfNine = 0; for (Int i = 0; i < digits; i++) { if (Int64(fract / Math::Pow(10, i)) % 10 == 9) nOfNine++; else break; } if (nOfNull > 0) fract = (Int64) (fract / Math::Pow(10, nOfNull)); else if (nOfNine > 0) fract = (Int64) (fract / Math::Pow(10, nOfNine)) + 1; String string = Number(Math::Floor(Math::Abs(floatValue))).ToIntString(); if (nOfNine == digits) { string = Number(Math::Floor(Math::Abs(floatValue)) + 1).ToIntString(); } else if (fract > 0) { string.Append(kPoint); for (Int i = 0; i < lead; i++) string.Append(kZero); string.Append(Number(fract).ToIntString()); } if (floatValue < 0) string = String(kMinus).Append(string); return string; } S::String S::Number::ToHexString(Int length) const { String string; Int stringPos = 0; for (Int i = 0; i < 16; i++) { if (((intValue >> (4 * (15 - i))) & 15) >= 10) string[stringPos++] = 'a' + ((intValue >> (4 * (15 - i))) & 15) - 10; else if (((intValue >> (4 * (15 - i))) & 15) >= 1) string[stringPos++] = '0' + ((intValue >> (4 * (15 - i))) & 15); else if (stringPos > 0) string[stringPos++] = '0'; } if (length != -1) { /* Add leading zeros if necessary. */ if (string.Length() < length) string = String().FillN('0', length - string.Length()).Append(string); /* Cut string if too long. */ if (string.Length() > length) string = string.Tail(length); } return string; } smooth-0.9.11~git20260403.0230c0da/classes/misc/string.cpp000066400000000000000000000622151516402577000223700ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __WIN32__ # include #endif namespace smooth { typedef Array BufferArray; static multithread (BufferArray *) allocatedBuffers = NIL; static multithread (Buffer *) iconvBuffer = NIL; static multithread (char *) inputFormat = NIL; static multithread (char *) outputFormat = NIL; static Bool initialized = False; Int ConvertString(const char *, Int, const char *, char *, Int, const char *); }; S::Int addStringInitTmp = S::AddInitFunction(&S::String::Initialize); S::Int addStringFreeTmp = S::AddFreeFunction(&S::String::Free); S::String::String(const int nil) { } S::String::String(const char *iString) { *this = iString; } S::String::String(const wchar_t *iString) { *this = iString; } S::String::String(const String &iString) { *this = iString; } S::String::~String() { } S::Int S::String::Initialize() { initialized = True; return Success(); } S::Int S::String::Free() { /* Delete all temporarily allocated string buffers. */ DeleteTemporaryBuffers(True); return Success(); } const char *S::String::GetDefaultEncoding() { #ifdef __WIN32__ static char encoding[16] = { }; if (strlen(encoding) > 0) return encoding; /* Find system codepage. */ Int codePage = GetACP(); if (codePage != CP_UTF8) { char buffer[12]; strncpy(encoding, "CP", 3); strncat(encoding, itoa(codePage, buffer, 10), 12); } else { strncpy(encoding, "UTF-8", 6); } return encoding; #else return "UTF-8"; #endif } S::Void S::String::AddTemporaryBuffer(char *buffer) { /* Free old buffers and add new. */ if (allocatedBuffers == NIL) allocatedBuffers = new BufferArray(); if (allocatedBuffers->Length() >= 8) DeleteTemporaryBuffers(); allocatedBuffers->Add(buffer); } S::Void S::String::DeleteTemporaryBuffers(Bool all) { /* Free all but the most recent 8 buffers. */ if (allocatedBuffers != NIL) { Int nOfEntries = allocatedBuffers->Length(); for (Int i = 0; i < nOfEntries - (all ? 0 : 8); i++) { delete [] allocatedBuffers->GetFirst(); allocatedBuffers->RemoveNth(0); } if (all) { delete allocatedBuffers; allocatedBuffers = NIL; } } /* When purging all, also free iconv buffer and I/O format strings. */ if (all) { if (iconvBuffer) delete iconvBuffer; if (inputFormat != NIL) delete [] inputFormat; if (outputFormat != NIL) delete [] outputFormat; inputFormat = NIL; outputFormat = NIL; } } S::Void S::String::Clean() { wString.Resize(0); } S::UnsignedInt32 S::String::ComputeCRC32() const { if (wString.Size() == 0) return 0; return Hash::CRC32::Compute((UnsignedByte *) (wchar_t *) wString, Length() * sizeof(wchar_t)); } S::UnsignedInt64 S::String::ComputeCRC64() const { if (wString.Size() == 0) return 0; return Hash::CRC64::Compute((UnsignedByte *) (wchar_t *) wString, Length() * sizeof(wchar_t)); } S::String S::String::EncodeBase64() const { if (wString.Size() == 0) return NIL; const char *utf8string = ConvertTo("UTF-8"); int length = strlen(utf8string); Buffer buffer(length); strncpy((char *) (UnsignedByte *) buffer, utf8string, length); return Encoding::Base64(buffer).Encode(); } S::String S::String::DecodeBase64() const { if (wString.Size() == 0) return NIL; Buffer buffer; String string; Encoding::Base64(buffer).Decode(*this); string.ImportFrom("UTF-8", (char *) (UnsignedByte *) buffer); return string; } S::Bool S::String::IsANSI(const String &string) { return !IsUnicode(string); } S::Bool S::String::IsUnicode(const String &string) { const wchar_t *chars = string; Int length = string.Length(); for (Int i = 0; i < length; i++) { if ( chars[i] < 0x20 || chars[i] > 0xFF || (chars[i] >= 0x80 && chars[i] < 0xA0)) return True; } return False; } const char *S::String::GetInputFormat() { if (inputFormat == NIL) return GetDefaultEncoding(); return inputFormat; } const char *S::String::SetInputFormat(const char *iFormat) { if (iFormat == NIL) return SetInputFormat(GetDefaultEncoding()); /* Return immediately if requested format equals current. */ if (inputFormat != NIL && strcmp(iFormat, inputFormat) == 0) return inputFormat; /* Backup input format and set new one. */ char *previousInputFormat = inputFormat; inputFormat = NIL; if (strcmp(iFormat, GetDefaultEncoding()) != 0) { int length = strlen(iFormat) + 1; inputFormat = new char [length]; strncpy(inputFormat, iFormat, length); } /* Add previous format to temporary buffers list. */ if (previousInputFormat != NIL) { AddTemporaryBuffer(previousInputFormat); return previousInputFormat; } return GetDefaultEncoding(); } const char *S::String::GetOutputFormat() { if (outputFormat == NIL) return GetDefaultEncoding(); return outputFormat; } const char *S::String::SetOutputFormat(const char *oFormat) { if (oFormat == NIL) return SetOutputFormat(GetDefaultEncoding()); /* Return immediately if requested format equals current. */ if (outputFormat != NIL && strcmp(oFormat, outputFormat) == 0) return outputFormat; /* Backup output format and set new one. */ char *previousOutputFormat = outputFormat; outputFormat = NIL; if (strcmp(oFormat, GetDefaultEncoding()) != 0) { int length = strlen(oFormat) + 1; outputFormat = new char [length]; strncpy(outputFormat, oFormat, length); } /* Add previous format to temporary buffers list. */ if (previousOutputFormat != NIL) { AddTemporaryBuffer(previousOutputFormat); return previousOutputFormat; } return GetDefaultEncoding(); } const char *S::String::GetInternalFormat() { static char *internalFormat = NIL; if (internalFormat == NIL) { UnsignedInt16 bom = 0xFEFF; if (sizeof(wchar_t) == 2) internalFormat = (char *) (((UnsignedInt8 *) &bom)[0] == 0xFF ? "UTF-16LE" : "UTF-16BE"); else if (sizeof(wchar_t) == 4) internalFormat = (char *) (((UnsignedInt8 *) &bom)[0] == 0xFF ? "UTF-32LE" : "UTF-32BE"); } return internalFormat; } S::Int S::String::ImportFrom(const char *format, const char *str) { Clean(); if (str == NIL) return Success(); Int width = 1; if (strncmp(format, "UCS-4", 5) == 0) width = 4; else if (strncmp(format, "UCS-2", 5) == 0) width = 2; else if (strncmp(format, "UTF-32", 6) == 0) width = 4; else if (strncmp(format, "UTF-16", 6) == 0) width = 2; else if (strncmp(format, "CSUCS4", 6) == 0) width = 4; else if (strncmp(format, "ISO-10646-UCS-4", 15) == 0) width = 4; else if (strncmp(format, "ISO-10646-UCS-2", 15) == 0) width = 2; else if (strncmp(format, "UNICODELITTLE", 13) == 0) width = 2; else if (strncmp(format, "UNICODEBIG", 10) == 0) width = 2; else if (strncmp(format, "CSUNICODE", 9) == 0) width = 2; else if (strncmp(format, "UNICODE-1-1", 11) == 0) width = 2; else if (strncmp(format, "CSUNICODE11", 11) == 0) width = 2; Int length = -1; if (width == 1) while (true) { if (((char *) str)[++length] == 0) { length *= 1; break; } } else if (width == 2) while (true) { if (((short *) str)[++length] == 0) { length *= 2; break; } } else if (width == 4) while (true) { if (((int *) str)[++length] == 0) { length *= 4; break; } } Int size = ConvertString(str, length, format, NIL, 0, GetInternalFormat()); if (size < 0 && strcmp(format, "ISO-8859-1") != 0) return ImportFrom("ISO-8859-1", str); else if (size < 0) return Error(); size = size / sizeof(wchar_t) + 1; wString.Resize(size); ConvertString(str, length, format, (char *) (wchar_t *) wString, size * sizeof(wchar_t), GetInternalFormat()); wString[size - 1] = 0; return Success(); } char *S::String::ConvertTo(const char *encoding) const { Int size = Length() + 1; if (size == 1) return NIL; Int bufferSize = ConvertString((char *) (wchar_t *) wString, size * sizeof(wchar_t), GetInternalFormat(), NIL, 0, encoding); if (bufferSize == -1) bufferSize = ConvertString((char *) (wchar_t *) wString, size * sizeof(wchar_t), GetInternalFormat(), NIL, 0, "ISO-8859-1"); char *buffer = NIL; if (bufferSize <= 0) { Int length = Length(); buffer = new char [length + 1]; ConvertString((char *) (wchar_t *) wString, size * sizeof(wchar_t), GetInternalFormat(), buffer, length + 1, encoding); for (Int i = -bufferSize; i < length; i++) buffer[i] = '?'; buffer[length] = 0; } else { buffer = new char [bufferSize + 1]; ConvertString((char *) (wchar_t *) wString, size * sizeof(wchar_t), GetInternalFormat(), buffer, bufferSize + 1, encoding); } AddTemporaryBuffer(buffer); return buffer; } wchar_t &S::String::operator [](int n) { static wchar_t dummy = 0; if (n < 0) return dummy; if (n + 1 >= wString.Size()) { Int length = Length(); /* Allocate more memory than actually * needed to speed up string operations. */ wString.Resize(n + Math::Max(10, Math::Min(n / 10, 100000))); wmemset(wString + length, 0, wString.Size() - length); } return wString[n]; } wchar_t S::String::operator []( int n) const { if (n < 0 || n + 1 >= wString.Size()) return 0; return wString[n]; } S::String::operator char *() const { return ConvertTo(GetOutputFormat()); } S::String::operator wchar_t *() const { return wString; } S::String &S::String::operator =(const int nil) { Clean(); return *this; } S::String &S::String::operator =(const char *newString) { Clean(); if (newString != NIL) ImportFrom(GetInputFormat(), newString); return *this; } S::String &S::String::operator =(const wchar_t *newString) { Clean(); if (newString != NIL) { Int size = wcslen(newString) + 1; wString.Resize(size); wcsncpy(wString, newString, size); } return *this; } S::String &S::String::operator =(const String &newString) { if (&newString == this) return *this; Clean(); if (newString.wString.Size() > 0) { Int size = newString.wString.Size(); wString.Resize(size); wcsncpy(wString, newString.wString, size); } return *this; } S::Bool S::String::operator ==(const int nil) const { if (wString.Size() == 0) return True; if (wString[0] == 0) return True; else return False; } S::Bool S::String::operator ==(const char *str) const { if (wString.Size() == 0 && str == NIL) return True; if (wString.Size() == 0 && str != NIL) if (str[0] == 0) return True; if (wString.Size() != 0 && str == NIL) if (wString[0] == 0) return True; if (wString.Size() == 0 || str == NIL) return False; if (!Compare(str)) return True; else return False; } S::Bool S::String::operator ==(const wchar_t *str) const { if (wString.Size() == 0 && str == NIL) return True; if (wString.Size() == 0 && str != NIL) if (str[0] == 0) return True; if (wString.Size() != 0 && str == NIL) if (wString[0] == 0) return True; if (wString.Size() == 0 || str == NIL) return False; if (!Compare(str)) return True; else return False; } S::Bool S::String::operator ==(const String &str) const { if (wString.Size() == 0 && str.wString.Size() == 0) return True; if (wString.Size() == 0 && str.wString.Size() != 0) if (str.wString[0] == 0) return True; if (wString.Size() != 0 && str.wString.Size() == 0) if (wString[0] == 0) return True; if (wString.Size() == 0 || str.wString.Size() == 0) return False; if (!Compare(str)) return True; else return False; } S::Bool S::String::operator !=(const int nil) const { if (wString.Size() == 0) return False; if (wString[0] == 0) return False; else return True; } S::Bool S::String::operator !=(const char *str) const { if (wString.Size() == 0 && str == NIL) return False; if (wString.Size() == 0 && str != NIL) if (str[0] == 0) return False; if (wString.Size() != 0 && str == NIL) if (wString[0] == 0) return False; if (wString.Size() == 0 || str == NIL) return True; if (Compare(str) != 0) return True; else return False; } S::Bool S::String::operator !=(const wchar_t *str) const { if (wString.Size() == 0 && str == NIL) return False; if (wString.Size() == 0 && str != NIL) if (str[0] == 0) return False; if (wString.Size() != 0 && str == NIL) if (wString[0] == 0) return False; if (wString.Size() == 0 || str == NIL) return True; if (Compare(str) != 0) return True; else return False; } S::Bool S::String::operator !=(const String &str) const { if (wString.Size() == 0 && str.wString.Size() == 0) return False; if (wString.Size() == 0 && str.wString.Size() != 0) if (str.wString[0] == 0) return False; if (wString.Size() != 0 && str.wString.Size() == 0) if (wString[0] == 0) return False; if (wString.Size() == 0 || str.wString.Size() == 0) return True; if (Compare(str) != 0) return True; else return False; } S::Int S::String::Length() const { if (wString.Size() == 0) return 0; return wcslen(wString); } S::Int S::String::Find(const String &str) const { if (str == NIL) return 0; if (*this == NIL) return -1; wchar_t* start = wcsstr(wString, str.wString); if (start != NIL) return start - wString; return -1; } S::Int S::String::FindLast(const String &str) const { if (str == NIL) return Length(); Int len1 = Length(); Int len2 = str.Length(); for (Int i = len1 - len2; i >= 0; i--) { if (wcsncmp(wString + i, str.wString, len2) == 0) return i; } return -1; } S::String &S::String::Append(const String &str) { if (str == NIL) return *this; Int len1 = Length(); Int len2 = str.Length(); wString.Resize(len1 + len2 + 1); wcsncpy(wString + len1, str.wString, len2); wString[len1 + len2] = 0; return *this; } S::String S::String::Append(const String &str) const { return String(*this).Append(str); } S::String &S::String::Replace(const String &str1, const String &str2) { if (str1 == NIL) return *this; Int len1 = Length(); Int len2 = str1.Length(); Int len3 = str2.Length(); for (Int i = 0; i <= len1 - len2; i++) { if (wcsncmp(wString + i, str1.wString, len2) == 0) { if (len2 != len3) { if (len3 > len2) wString.Resize(len1 + 1 + (len3 - len2)); wmemmove(wString + i + len3, wString + i + len2, len1 - i - len2 + 1); len1 += (len3 - len2); } if (len3 > 0) wcsncpy(wString + i, str2.wString, len3); i += len3 - 1; } } return *this; } S::String S::String::Replace(const String &str1, const String &str2) const { return String(*this).Replace(str1, str2); } S::String &S::String::Copy(const String &str) { *this = str; return *this; } S::String &S::String::CopyN(const String &str, const Int n) { Clean(); if (n > 0) { wString.Resize(n + 1); wcsncpy(wString, str.wString, n); wString[n] = 0; } return *this; } S::Bool S::String::Contains(const String &str) const { if (Find(str) >= 0) return True; else return False; } S::Int S::String::Compare(const String &str) const { Int len1 = Length(); Int len2 = str.Length(); if (len1 != len2) return len1 - len2; else if (len1 > 0 && wcsncmp(wString, str.wString, len1) != 0) return 1; return 0; } S::Int S::String::CompareN(const String &str, Int n) const { if (n == 0) return 0; if (Length() < n) return 1; if (wcsncmp(wString, str.wString, n) != 0) return 1; return 0; } S::Bool S::String::StartsWith(const String &str) const { if (str == NIL) return True; Int len1 = Length(); Int len2 = str.Length(); if (len1 >= len2) { if (wcsncmp(wString, str.wString, len2) != 0) return False; return True; } return False; } S::Bool S::String::EndsWith(const String &str) const { if (str == NIL) return True; Int len1 = Length(); Int len2 = str.Length(); if (len1 >= len2) { if (wcsncmp(wString + len1 - len2, str.wString, len2) != 0) return False; return True; } return False; } S::String S::String::SubString(Int start, Int number) const { if (number <= 0 || start < 0 || start >= Length()) return NIL; String subString; subString.wString.Resize(number + 1); wcsncpy(subString.wString, wString + start, number); subString.wString[number] = 0; return subString; } S::String S::String::Head(Int n) const { return SubString(0, n); } S::String S::String::Tail(Int n) const { return SubString(Length() - n, n); } S::String S::String::Trim() const { Int length = Length(); Int triml = 0; Int trimr = 0; for (Int i = 0; i < length; i++) { if ((*this)[i] == ' ' || (*this)[i] == '\t' || (*this)[i] == '\n' || (*this)[i] == '\r' || (*this)[i] == '\0' || (*this)[i] == '\x0B') triml++; else break; } for (Int i = length - 1; i >= 0; i--) { if ((*this)[i] == ' ' || (*this)[i] == '\t' || (*this)[i] == '\n' || (*this)[i] == '\r' || (*this)[i] == '\0' || (*this)[i] == '\x0B') trimr++; else break; } return SubString(triml, length - triml - trimr); } S::String &S::String::Fill(const Int value) { if (*this == NIL) return *this; wmemset(wString, value, Length()); return *this; } S::String &S::String::FillN(const Int value, const Int count) { Clean(); if (count > 0) { wString.Resize(count + 1); wmemset(wString, value, count); wString[count] = 0; } return *this; } S::Int64 S::String::ToInt() const { return Number::FromIntString(*this); } S::Float S::String::ToFloat() const { return Number::FromFloatString(*this); } S::String S::String::FromInt(const Int64 value) { return Number(value).ToIntString(); } S::String S::String::FromFloat(Float value) { return Number(value).ToFloatString(); } S::Array S::String::Explode(const String &delimiter) const { /* Split string and add entries to array. */ Array array; Int length = Length(); for (Int i = 0; i < length; ) { Int index = SubString(i, length - i).Find(delimiter); String part; if (index == -1) part = SubString(i, length - i); else part = SubString(i, index); array.Add(part); i += part.Length() + delimiter.Length(); } return array; } S::String S::String::Implode(const Array &array, const String &delimiter) { String string; for (Int i = 0; i < array.Length(); i++) { if (i > 0) string.Append(delimiter); string.Append(array.GetNth(i)); } return string; } S::Int S::ConvertString(const char *inBuffer, Int inBytes, const char *inEncoding, char *outBuffer, Int outBytes, const char *outEncoding) { /* Copy string if both encodings are the same. */ if (strcmp(inEncoding, outEncoding) == 0) { if (outBuffer == NIL) return inBytes; if (inBytes >= outBytes) return 0; if (inBytes < outBytes && inBytes > 0) memcpy(outBuffer, inBuffer, inBytes); return inBytes; } /* Switch bytes for conversion between little and big endian. */ if ((strcmp(inEncoding, "UTF-16LE") == 0 && strcmp(outEncoding, "UTF-16BE") == 0) || (strcmp(inEncoding, "UTF-16BE") == 0 && strcmp(outEncoding, "UTF-16LE") == 0)) { if (outBuffer == NIL) return inBytes; if (inBytes >= outBytes) return 0; if (inBytes < outBytes && inBytes > 0) { for (Int i = 0; i < inBytes / 2; i++) ((UnsignedInt16 *) outBuffer)[i] = ((((UnsignedInt16 *) inBuffer)[i] & 255) << 8) | (((UnsignedInt16 *) inBuffer)[i] >> 8); } return inBytes; } /* Convert using iconv/libiconv. */ if (Setup::useIconv) { /* Open and configure iconv. */ iconv_t cd = iconv_open(outEncoding, inEncoding); if (cd != (iconv_t) -1) { #if _LIBICONV_VERSION >= 0x0108 int on = 1; iconvctl(cd, ICONV_SET_TRANSLITERATE, &on); #endif /* Assign output buffer if not provided. */ Buffer *outBufferObject = NIL; if (outBuffer == NIL) { outBytes = inBytes * 8; #if defined(__APPLE__) || defined(__OpenBSD__) /* Work around C++ static object initialization order issues. * * This can be removed once we enable __thread or thread_local * for macOS and OpenBSD builds. On macOS this can be done when * the target version is raised to 10.7 or later. */ if (!initialized) { outBufferObject = new Buffer(outBytes); outBuffer = *outBufferObject; } else #endif { if (iconvBuffer == NIL) iconvBuffer = new Buffer(); if (iconvBuffer->Size() > 4096 && outBytes < 256) iconvBuffer->Free(); iconvBuffer->Resize(outBytes); outBuffer = *iconvBuffer; } } /* Perform actual conversion. */ size_t inBytesLeft = inBytes; size_t outBytesLeft = outBytes; char **outPointer = &outBuffer; char **inPointer = const_cast(&inBuffer); while (inBytesLeft) { if (iconv(cd, inPointer, &inBytesLeft, outPointer, &outBytesLeft) == (size_t) -1) break; } iconv_close(cd); if (outBufferObject) delete outBufferObject; Int size = !outBytesLeft ? 0 : outBytes - outBytesLeft; if (inBytesLeft) size *= -1; return size; } } #ifdef __WIN32__ /* Convert to UTF-16LE on Windows. */ if (strcmp(outEncoding, "UTF-16LE") == 0) { Int codePage = CP_ACP; if (strcmp(inEncoding, "UTF-8") == 0) codePage = CP_UTF8; else if (strcmp(inEncoding, "UTF-7") == 0) codePage = CP_UTF7; else if (strcmp(inEncoding, "ISO-8859-1") == 0) codePage = 28591; else if (strcmp(inEncoding, "ISO-8859-2") == 0) codePage = 28592; else if (strcmp(inEncoding, "ISO-8859-3") == 0) codePage = 28593; else if (strcmp(inEncoding, "ISO-8859-4") == 0) codePage = 28594; else if (strcmp(inEncoding, "ISO-8859-5") == 0) codePage = 28595; else if (strcmp(inEncoding, "ISO-8859-6") == 0) codePage = 28596; else if (strcmp(inEncoding, "ISO-8859-7") == 0) codePage = 28597; else if (strcmp(inEncoding, "ISO-8859-8") == 0) codePage = 28598; else if (strcmp(inEncoding, "ISO-8859-9") == 0) codePage = 28599; else if (strcmp(inEncoding, "ISO-8859-15") == 0) codePage = 28605; else if (strcmp(inEncoding, "KOI8-R") == 0) codePage = 20866; else if (strcmp(inEncoding, "KOI8-U") == 0) codePage = 21866; else if (strcmp(inEncoding, "SHIFT-JIS") == 0) codePage = 932; else if (strcmp(inEncoding, "GBK") == 0) codePage = 936; else if (strcmp(inEncoding, "BIG-5") == 0) codePage = 950; else if (strcmp(inEncoding, "ISO-2022-JP") == 0) codePage = 50220; else if (strcmp(inEncoding, "ISO-2022-KR") == 0) codePage = 50225; else if (strcmp(inEncoding, "ISO-2022-CN") == 0) codePage = 50227; if (inEncoding[0] == 'C' && inEncoding[1] == 'P') codePage = atoi(inEncoding + 2); Int size = MultiByteToWideChar(codePage, 0, inBuffer, -1, NIL, 0) * sizeof(wchar_t); /* Codepage not installed? Let's try CP_ACP! */ if (size == 0 && GetLastError() == ERROR_INVALID_PARAMETER) size = MultiByteToWideChar(codePage = CP_ACP, 0, inBuffer, -1, NIL, 0) * sizeof(wchar_t); if (outBuffer != NIL) { if (size < outBytes && size > 0) MultiByteToWideChar(codePage, 0, inBuffer, -1, (wchar_t *) outBuffer, size / sizeof(wchar_t)); if (size >= outBytes) size = 0; } return size; } /* Convert from UTF-16LE on Windows. */ if (strcmp(inEncoding, "UTF-16LE") == 0) { Int codePage = CP_ACP; if (strcmp(outEncoding, "UTF-8") == 0) codePage = CP_UTF8; else if (strcmp(outEncoding, "UTF-7") == 0) codePage = CP_UTF7; else if (strcmp(outEncoding, "ISO-8859-1") == 0) codePage = 28591; else if (strcmp(outEncoding, "ISO-8859-2") == 0) codePage = 28592; else if (strcmp(outEncoding, "ISO-8859-3") == 0) codePage = 28593; else if (strcmp(outEncoding, "ISO-8859-4") == 0) codePage = 28594; else if (strcmp(outEncoding, "ISO-8859-5") == 0) codePage = 28595; else if (strcmp(outEncoding, "ISO-8859-6") == 0) codePage = 28596; else if (strcmp(outEncoding, "ISO-8859-7") == 0) codePage = 28597; else if (strcmp(outEncoding, "ISO-8859-8") == 0) codePage = 28598; else if (strcmp(outEncoding, "ISO-8859-9") == 0) codePage = 28599; else if (strcmp(outEncoding, "ISO-8859-15") == 0) codePage = 28605; else if (strcmp(outEncoding, "KOI8-R") == 0) codePage = 20866; else if (strcmp(outEncoding, "KOI8-U") == 0) codePage = 21866; else if (strcmp(outEncoding, "SHIFT-JIS") == 0) codePage = 932; else if (strcmp(outEncoding, "GBK") == 0) codePage = 936; else if (strcmp(outEncoding, "BIG-5") == 0) codePage = 950; else if (strcmp(outEncoding, "ISO-2022-JP") == 0) codePage = 50220; else if (strcmp(outEncoding, "ISO-2022-KR") == 0) codePage = 50225; else if (strcmp(outEncoding, "ISO-2022-CN") == 0) codePage = 50227; if (outEncoding[0] == 'C' && outEncoding[1] == 'P') codePage = atoi(outEncoding + 2); Int size = WideCharToMultiByte(codePage, 0, (wchar_t *) inBuffer, -1, NIL, 0, NIL, NIL); /* Codepage not installed? Let's try CP_ACP! */ if (size == 0 && GetLastError() == ERROR_INVALID_PARAMETER) size = WideCharToMultiByte(codePage = CP_ACP, 0, (wchar_t *) inBuffer, -1, NIL, 0, NIL, NIL); if (outBuffer != NIL) { if (size < outBytes && size > 0) WideCharToMultiByte(codePage, 0, (wchar_t *) inBuffer, -1, outBuffer, size, NIL, NIL); if (size >= outBytes) size = 0; } return size; } #endif return -1; } smooth-0.9.11~git20260403.0230c0da/classes/misc/string_case.cpp000077500000000000000000001153521516402577000233670ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2015 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::String S::String::ToUpper() const { String retVal = *this; Int length = Length(); for (Int i = 0; i < length; i++) { wchar_t value = (*this)[i]; if (value >= 0x61 && value <= 0x7a) retVal[i] = value - 0x20; // Alphabet else if (value == 0xb5) retVal[i] = 0x39c; // Single character else if (value >= 0xe0 && value <= 0xf6) retVal[i] = value - 0x20; // Alphabet else if (value >= 0xf8 && value <= 0xfe) retVal[i] = value - 0x20; // Alphabet else if (value == 0xff) retVal[i] = 0x178; // Single character else if (value >= 0x101 && value <= 0x12f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x131) retVal[i] = 0x49; // Single character else if (value >= 0x133 && value <= 0x137 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x13a && value <= 0x148 && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x14b && value <= 0x177 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x17a && value <= 0x17e && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x17f) retVal[i] = 0x53; // Single character else if (value == 0x180) retVal[i] = 0x243; // Single character else if (value >= 0x183 && value <= 0x185 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x188) retVal[i] = 0x187; // Single character else if (value == 0x18c) retVal[i] = 0x18b; // Single character else if (value == 0x192) retVal[i] = 0x191; // Single character else if (value == 0x195) retVal[i] = 0x1f6; // Single character else if (value == 0x199) retVal[i] = 0x198; // Single character else if (value == 0x19a) retVal[i] = 0x23d; // Single character else if (value == 0x19e) retVal[i] = 0x220; // Single character else if (value >= 0x1a1 && value <= 0x1a5 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1a8) retVal[i] = 0x1a7; // Single character else if (value == 0x1ad) retVal[i] = 0x1ac; // Single character else if (value == 0x1b0) retVal[i] = 0x1af; // Single character else if (value >= 0x1b4 && value <= 0x1b6 && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1b9) retVal[i] = 0x1b8; // Single character else if (value == 0x1bd) retVal[i] = 0x1bc; // Single character else if (value == 0x1bf) retVal[i] = 0x1f7; // Single character else if (value == 0x1c5) retVal[i] = 0x1c4; // Single character else if (value == 0x1c6) retVal[i] = 0x1c4; // Single character else if (value == 0x1c8) retVal[i] = 0x1c7; // Single character else if (value == 0x1c9) retVal[i] = 0x1c7; // Single character else if (value == 0x1cb) retVal[i] = 0x1ca; // Single character else if (value == 0x1cc) retVal[i] = 0x1ca; // Single character else if (value >= 0x1ce && value <= 0x1dc && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1dd) retVal[i] = 0x18e; // Single character else if (value >= 0x1df && value <= 0x1ef && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1f2) retVal[i] = 0x1f1; // Single character else if (value == 0x1f3) retVal[i] = 0x1f1; // Single character else if (value == 0x1f5) retVal[i] = 0x1f4; // Single character else if (value >= 0x1f9 && value <= 0x21f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x223 && value <= 0x233 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x23c) retVal[i] = 0x23b; // Single character else if (value == 0x242) retVal[i] = 0x241; // Single character else if (value >= 0x247 && value <= 0x24f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x250) retVal[i] = 0x2c6f; // Single character else if (value == 0x251) retVal[i] = 0x2c6d; // Single character else if (value == 0x253) retVal[i] = 0x181; // Single character else if (value == 0x254) retVal[i] = 0x186; // Single character else if (value >= 0x256 && value <= 0x257) retVal[i] = value - 0xcd; // Alphabet else if (value == 0x259) retVal[i] = 0x18f; // Single character else if (value == 0x25b) retVal[i] = 0x190; // Single character else if (value == 0x260) retVal[i] = 0x193; // Single character else if (value == 0x263) retVal[i] = 0x194; // Single character else if (value == 0x268) retVal[i] = 0x197; // Single character else if (value == 0x269) retVal[i] = 0x196; // Single character else if (value == 0x26b) retVal[i] = 0x2c62; // Single character else if (value == 0x26f) retVal[i] = 0x19c; // Single character else if (value == 0x271) retVal[i] = 0x2c6e; // Single character else if (value == 0x272) retVal[i] = 0x19d; // Single character else if (value == 0x275) retVal[i] = 0x19f; // Single character else if (value == 0x27d) retVal[i] = 0x2c64; // Single character else if (value == 0x280) retVal[i] = 0x1a6; // Single character else if (value == 0x283) retVal[i] = 0x1a9; // Single character else if (value == 0x288) retVal[i] = 0x1ae; // Single character else if (value == 0x289) retVal[i] = 0x244; // Single character else if (value >= 0x28a && value <= 0x28b) retVal[i] = value - 0xd9; // Alphabet else if (value == 0x28c) retVal[i] = 0x245; // Single character else if (value == 0x292) retVal[i] = 0x1b7; // Single character else if (value == 0x345) retVal[i] = 0x399; // Single character else if (value >= 0x371 && value <= 0x373 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x377) retVal[i] = 0x376; // Single character else if (value >= 0x37b && value <= 0x37d) retVal[i] = value + 0x82; // Alphabet else if (value == 0x3ac) retVal[i] = 0x386; // Single character else if (value >= 0x3ad && value <= 0x3af) retVal[i] = value - 0x25; // Alphabet else if (value >= 0x3b1 && value <= 0x3c1) retVal[i] = value - 0x20; // Alphabet else if (value == 0x3c2) retVal[i] = 0x3a3; // Single character else if (value >= 0x3c3 && value <= 0x3cb) retVal[i] = value - 0x20; // Alphabet else if (value == 0x3cc) retVal[i] = 0x38c; // Single character else if (value >= 0x3cd && value <= 0x3ce) retVal[i] = value - 0x3f; // Alphabet else if (value == 0x3d0) retVal[i] = 0x392; // Single character else if (value == 0x3d1) retVal[i] = 0x398; // Single character else if (value == 0x3d5) retVal[i] = 0x3a6; // Single character else if (value == 0x3d6) retVal[i] = 0x3a0; // Single character else if (value == 0x3d7) retVal[i] = 0x3cf; // Single character else if (value >= 0x3d9 && value <= 0x3ef && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x3f0) retVal[i] = 0x39a; // Single character else if (value == 0x3f1) retVal[i] = 0x3a1; // Single character else if (value == 0x3f2) retVal[i] = 0x3f9; // Single character else if (value == 0x3f5) retVal[i] = 0x395; // Single character else if (value == 0x3f8) retVal[i] = 0x3f7; // Single character else if (value == 0x3fb) retVal[i] = 0x3fa; // Single character else if (value >= 0x430 && value <= 0x44f) retVal[i] = value - 0x20; // Alphabet else if (value >= 0x450 && value <= 0x45f) retVal[i] = value - 0x50; // Alphabet else if (value >= 0x461 && value <= 0x481 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x48b && value <= 0x4bf && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x4c2 && value <= 0x4ce && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x4cf) retVal[i] = 0x4c0; // Single character else if (value >= 0x4d1 && value <= 0x523 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x561 && value <= 0x586) retVal[i] = value - 0x30; // Alphabet else if (value == 0x1d79) retVal[i] = 0xa77d; // Single character else if (value == 0x1d7d) retVal[i] = 0x2c63; // Single character else if (value >= 0x1e01 && value <= 0x1e95 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1e9b) retVal[i] = 0x1e60; // Single character else if (value >= 0x1ea1 && value <= 0x1eff && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x1f00 && value <= 0x1f07) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f10 && value <= 0x1f15) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f20 && value <= 0x1f27) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f30 && value <= 0x1f37) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f40 && value <= 0x1f45) retVal[i] = value + 0x8; // Alphabet else if (value == 0x1f51) retVal[i] = 0x1f59; // Single character else if (value == 0x1f53) retVal[i] = 0x1f5b; // Single character else if (value == 0x1f55) retVal[i] = 0x1f5d; // Single character else if (value == 0x1f57) retVal[i] = 0x1f5f; // Single character /* Work around stupid MSVC's limit on alternatives... * ---- * This is not generated automatically, but * needs to be inserted manually here. */ if (value >= 0x1f60 && value <= 0x1f67) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f70 && value <= 0x1f71) retVal[i] = value + 0x4a; // Alphabet else if (value >= 0x1f72 && value <= 0x1f75) retVal[i] = value + 0x56; // Alphabet else if (value >= 0x1f76 && value <= 0x1f77) retVal[i] = value + 0x64; // Alphabet else if (value >= 0x1f78 && value <= 0x1f79) retVal[i] = value + 0x80; // Alphabet else if (value >= 0x1f7a && value <= 0x1f7b) retVal[i] = value + 0x70; // Alphabet else if (value >= 0x1f7c && value <= 0x1f7d) retVal[i] = value + 0x7e; // Alphabet else if (value >= 0x1f80 && value <= 0x1f87) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f90 && value <= 0x1f97) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1fa0 && value <= 0x1fa7) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1fb0 && value <= 0x1fb1) retVal[i] = value + 0x8; // Alphabet else if (value == 0x1fb3) retVal[i] = 0x1fbc; // Single character else if (value == 0x1fbe) retVal[i] = 0x399; // Single character else if (value == 0x1fc3) retVal[i] = 0x1fcc; // Single character else if (value >= 0x1fd0 && value <= 0x1fd1) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1fe0 && value <= 0x1fe1) retVal[i] = value + 0x8; // Alphabet else if (value == 0x1fe5) retVal[i] = 0x1fec; // Single character else if (value == 0x1ff3) retVal[i] = 0x1ffc; // Single character else if (value == 0x214e) retVal[i] = 0x2132; // Single character else if (value >= 0x2170 && value <= 0x217f) retVal[i] = value - 0x10; // Alphabet else if (value == 0x2184) retVal[i] = 0x2183; // Single character else if (value >= 0x24d0 && value <= 0x24e9) retVal[i] = value - 0x1a; // Alphabet else if (value >= 0x2c30 && value <= 0x2c5e) retVal[i] = value - 0x30; // Alphabet else if (value == 0x2c61) retVal[i] = 0x2c60; // Single character else if (value == 0x2c65) retVal[i] = 0x23a; // Single character else if (value == 0x2c66) retVal[i] = 0x23e; // Single character else if (value >= 0x2c68 && value <= 0x2c6c && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x2c73) retVal[i] = 0x2c72; // Single character else if (value == 0x2c76) retVal[i] = 0x2c75; // Single character else if (value >= 0x2c81 && value <= 0x2ce3 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x2d00 && value <= 0x2d25) retVal[i] = value - 0x1c60; // Alphabet else if (value >= 0xa641 && value <= 0xa65f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa663 && value <= 0xa66d && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa681 && value <= 0xa697 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa723 && value <= 0xa72f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa733 && value <= 0xa76f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa77a && value <= 0xa77c && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa77f && value <= 0xa787 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0xa78c) retVal[i] = 0xa78b; // Single character else if (value >= 0xff41 && value <= 0xff5a) retVal[i] = value - 0x20; // Alphabet } return retVal; } S::String S::String::ToLower() const { String retVal = *this; Int length = Length(); for (Int i = 0; i < length; i++) { wchar_t value = (*this)[i]; if (value >= 0x41 && value <= 0x5a) retVal[i] = value + 0x20; // Alphabet else if (value >= 0xc0 && value <= 0xd6) retVal[i] = value + 0x20; // Alphabet else if (value >= 0xd8 && value <= 0xde) retVal[i] = value + 0x20; // Alphabet else if (value >= 0x100 && value <= 0x12e && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x130) retVal[i] = 0x69; // Single character else if (value >= 0x132 && value <= 0x136 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0x139 && value <= 0x147 && (value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0x14a && value <= 0x176 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x178) retVal[i] = 0xff; // Single character else if (value >= 0x179 && value <= 0x17d && (value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x181) retVal[i] = 0x253; // Single character else if (value >= 0x182 && value <= 0x184 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x186) retVal[i] = 0x254; // Single character else if (value == 0x187) retVal[i] = 0x188; // Single character else if (value >= 0x189 && value <= 0x18a) retVal[i] = value + 0xcd; // Alphabet else if (value == 0x18b) retVal[i] = 0x18c; // Single character else if (value == 0x18e) retVal[i] = 0x1dd; // Single character else if (value == 0x18f) retVal[i] = 0x259; // Single character else if (value == 0x190) retVal[i] = 0x25b; // Single character else if (value == 0x191) retVal[i] = 0x192; // Single character else if (value == 0x193) retVal[i] = 0x260; // Single character else if (value == 0x194) retVal[i] = 0x263; // Single character else if (value == 0x196) retVal[i] = 0x269; // Single character else if (value == 0x197) retVal[i] = 0x268; // Single character else if (value == 0x198) retVal[i] = 0x199; // Single character else if (value == 0x19c) retVal[i] = 0x26f; // Single character else if (value == 0x19d) retVal[i] = 0x272; // Single character else if (value == 0x19f) retVal[i] = 0x275; // Single character else if (value >= 0x1a0 && value <= 0x1a4 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x1a6) retVal[i] = 0x280; // Single character else if (value == 0x1a7) retVal[i] = 0x1a8; // Single character else if (value == 0x1a9) retVal[i] = 0x283; // Single character else if (value == 0x1ac) retVal[i] = 0x1ad; // Single character else if (value == 0x1ae) retVal[i] = 0x288; // Single character else if (value == 0x1af) retVal[i] = 0x1b0; // Single character else if (value >= 0x1b1 && value <= 0x1b2) retVal[i] = value + 0xd9; // Alphabet else if (value >= 0x1b3 && value <= 0x1b5 && (value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x1b7) retVal[i] = 0x292; // Single character else if (value == 0x1b8) retVal[i] = 0x1b9; // Single character else if (value == 0x1bc) retVal[i] = 0x1bd; // Single character else if (value == 0x1c4) retVal[i] = 0x1c6; // Single character else if (value == 0x1c5) retVal[i] = 0x1c6; // Single character else if (value == 0x1c7) retVal[i] = 0x1c9; // Single character else if (value == 0x1c8) retVal[i] = 0x1c9; // Single character else if (value == 0x1ca) retVal[i] = 0x1cc; // Single character else if (value >= 0x1cb && value <= 0x1db && (value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0x1de && value <= 0x1ee && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x1f1) retVal[i] = 0x1f3; // Single character else if (value >= 0x1f2 && value <= 0x1f4 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x1f6) retVal[i] = 0x195; // Single character else if (value == 0x1f7) retVal[i] = 0x1bf; // Single character else if (value >= 0x1f8 && value <= 0x21e && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x220) retVal[i] = 0x19e; // Single character else if (value >= 0x222 && value <= 0x232 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x23a) retVal[i] = 0x2c65; // Single character else if (value == 0x23b) retVal[i] = 0x23c; // Single character else if (value == 0x23d) retVal[i] = 0x19a; // Single character else if (value == 0x23e) retVal[i] = 0x2c66; // Single character else if (value == 0x241) retVal[i] = 0x242; // Single character else if (value == 0x243) retVal[i] = 0x180; // Single character else if (value == 0x244) retVal[i] = 0x289; // Single character else if (value == 0x245) retVal[i] = 0x28c; // Single character else if (value >= 0x246 && value <= 0x24e && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0x370 && value <= 0x372 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x376) retVal[i] = 0x377; // Single character else if (value == 0x386) retVal[i] = 0x3ac; // Single character else if (value >= 0x388 && value <= 0x38a) retVal[i] = value + 0x25; // Alphabet else if (value == 0x38c) retVal[i] = 0x3cc; // Single character else if (value >= 0x38e && value <= 0x38f) retVal[i] = value + 0x3f; // Alphabet else if (value >= 0x391 && value <= 0x3aa) retVal[i] = value + 0x20; // Alphabet else if (value == 0x3cf) retVal[i] = 0x3d7; // Single character else if (value >= 0x3d8 && value <= 0x3ee && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x3f4) retVal[i] = 0x3b8; // Single character else if (value == 0x3f7) retVal[i] = 0x3f8; // Single character else if (value == 0x3f9) retVal[i] = 0x3f2; // Single character else if (value == 0x3fa) retVal[i] = 0x3fb; // Single character else if (value >= 0x3fd && value <= 0x3ff) retVal[i] = value - 0x82; // Alphabet else if (value >= 0x400 && value <= 0x40f) retVal[i] = value + 0x50; // Alphabet else if (value >= 0x410 && value <= 0x42f) retVal[i] = value + 0x20; // Alphabet else if (value >= 0x460 && value <= 0x480 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0x48a && value <= 0x4be && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x4c0) retVal[i] = 0x4cf; // Single character else if (value >= 0x4c1 && value <= 0x4cd && (value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0x4d0 && value <= 0x522 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0x531 && value <= 0x556) retVal[i] = value + 0x30; // Alphabet else if (value >= 0x10a0 && value <= 0x10c5) retVal[i] = value + 0x1c60; // Alphabet else if (value >= 0x1e00 && value <= 0x1e94 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x1e9e) retVal[i] = 0xdf; // Single character else if (value >= 0x1ea0 && value <= 0x1efe && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0x1f08 && value <= 0x1f0f) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1f18 && value <= 0x1f1d) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1f28 && value <= 0x1f2f) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1f38 && value <= 0x1f3f) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1f48 && value <= 0x1f4d) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1f59 && value <= 0x1f5c) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1f68 && value <= 0x1f6f) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1f88 && value <= 0x1f8f) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1f98 && value <= 0x1f9f) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1fa8 && value <= 0x1faf) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1fb8 && value <= 0x1fb9) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1fba && value <= 0x1fbb) retVal[i] = value - 0x4a; // Alphabet else if (value == 0x1fbc) retVal[i] = 0x1fb3; // Single character else if (value >= 0x1fc8 && value <= 0x1fcb) retVal[i] = value - 0x56; // Alphabet else if (value == 0x1fcc) retVal[i] = 0x1fc3; // Single character else if (value >= 0x1fd8 && value <= 0x1fd9) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1fda && value <= 0x1fdb) retVal[i] = value - 0x64; // Alphabet else if (value >= 0x1fe8 && value <= 0x1fe9) retVal[i] = value - 0x8; // Alphabet else if (value >= 0x1fea && value <= 0x1feb) retVal[i] = value - 0x70; // Alphabet else if (value == 0x1fec) retVal[i] = 0x1fe5; // Single character else if (value >= 0x1ff8 && value <= 0x1ff9) retVal[i] = value - 0x80; // Alphabet else if (value >= 0x1ffa && value <= 0x1ffb) retVal[i] = value - 0x7e; // Alphabet else if (value == 0x1ffc) retVal[i] = 0x1ff3; // Single character else if (value == 0x2126) retVal[i] = 0x3c9; // Single character else if (value == 0x212a) retVal[i] = 0x6b; // Single character else if (value == 0x212b) retVal[i] = 0xe5; // Single character else if (value == 0x2132) retVal[i] = 0x214e; // Single character else if (value >= 0x2160 && value <= 0x216f) retVal[i] = value + 0x10; // Alphabet else if (value == 0x2183) retVal[i] = 0x2184; // Single character else if (value >= 0x24b6 && value <= 0x24cf) retVal[i] = value + 0x1a; // Alphabet else if (value >= 0x2c00 && value <= 0x2c2e) retVal[i] = value + 0x30; // Alphabet /* Work around stupid MSVC's limit on alternatives... * ---- * This is not generated automatically, but * needs to be inserted manually here. */ if (value == 0x2c60) retVal[i] = 0x2c61; // Single character else if (value == 0x2c62) retVal[i] = 0x26b; // Single character else if (value == 0x2c63) retVal[i] = 0x1d7d; // Single character else if (value == 0x2c64) retVal[i] = 0x27d; // Single character else if (value >= 0x2c67 && value <= 0x2c6b && (value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0x2c6d) retVal[i] = 0x251; // Single character else if (value == 0x2c6e) retVal[i] = 0x271; // Single character else if (value == 0x2c6f) retVal[i] = 0x250; // Single character else if (value == 0x2c72) retVal[i] = 0x2c73; // Single character else if (value == 0x2c75) retVal[i] = 0x2c76; // Single character else if (value >= 0x2c80 && value <= 0x2ce2 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0xa640 && value <= 0xa660 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0xa664 && value <= 0xa66c && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0xa680 && value <= 0xa696 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0xa722 && value <= 0xa72e && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0xa732 && value <= 0xa76e && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value >= 0xa779 && value <= 0xa77b && (value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0xa77d) retVal[i] = 0x1d79; // Single character else if (value >= 0xa77e && value <= 0xa786 && !(value & 1)) retVal[i] = value + 0x1; // Special letters else if (value == 0xa78b) retVal[i] = 0xa78c; // Single character else if (value >= 0xff21 && value <= 0xff3a) retVal[i] = value + 0x20; // Alphabet } return retVal; } S::String S::String::ToTitle() const { String retVal = *this; Int length = Length(); for (Int i = 0; i < length; i++) { wchar_t value = (*this)[i]; if (value >= 0x61 && value <= 0x7a) retVal[i] = value - 0x20; // Alphabet else if (value == 0xb5) retVal[i] = 0x39c; // Single character else if (value >= 0xe0 && value <= 0xf6) retVal[i] = value - 0x20; // Alphabet else if (value >= 0xf8 && value <= 0xfe) retVal[i] = value - 0x20; // Alphabet else if (value == 0xff) retVal[i] = 0x178; // Single character else if (value >= 0x101 && value <= 0x12f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x131) retVal[i] = 0x49; // Single character else if (value >= 0x133 && value <= 0x137 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x13a && value <= 0x148 && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x14b && value <= 0x177 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x17a && value <= 0x17e && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x17f) retVal[i] = 0x53; // Single character else if (value == 0x180) retVal[i] = 0x243; // Single character else if (value >= 0x183 && value <= 0x185 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x188) retVal[i] = 0x187; // Single character else if (value == 0x18c) retVal[i] = 0x18b; // Single character else if (value == 0x192) retVal[i] = 0x191; // Single character else if (value == 0x195) retVal[i] = 0x1f6; // Single character else if (value == 0x199) retVal[i] = 0x198; // Single character else if (value == 0x19a) retVal[i] = 0x23d; // Single character else if (value == 0x19e) retVal[i] = 0x220; // Single character else if (value >= 0x1a1 && value <= 0x1a5 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1a8) retVal[i] = 0x1a7; // Single character else if (value == 0x1ad) retVal[i] = 0x1ac; // Single character else if (value == 0x1b0) retVal[i] = 0x1af; // Single character else if (value >= 0x1b4 && value <= 0x1b6 && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1b9) retVal[i] = 0x1b8; // Single character else if (value == 0x1bd) retVal[i] = 0x1bc; // Single character else if (value == 0x1bf) retVal[i] = 0x1f7; // Single character else if (value == 0x1c4) retVal[i] = 0x1c5; // Single character else if (value == 0x1c5) retVal[i] = 0x1c5; // Single character else if (value == 0x1c6) retVal[i] = 0x1c5; // Single character else if (value == 0x1c7) retVal[i] = 0x1c8; // Single character else if (value == 0x1c8) retVal[i] = 0x1c8; // Single character else if (value == 0x1c9) retVal[i] = 0x1c8; // Single character else if (value == 0x1ca) retVal[i] = 0x1cb; // Single character else if (value == 0x1cb) retVal[i] = 0x1cb; // Single character else if (value >= 0x1cc && value <= 0x1dc && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1dd) retVal[i] = 0x18e; // Single character else if (value >= 0x1df && value <= 0x1ef && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1f1) retVal[i] = 0x1f2; // Single character else if (value == 0x1f2) retVal[i] = 0x1f2; // Single character else if (value >= 0x1f3 && value <= 0x1f5 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x1f9 && value <= 0x21f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x223 && value <= 0x233 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x23c) retVal[i] = 0x23b; // Single character else if (value == 0x242) retVal[i] = 0x241; // Single character else if (value >= 0x247 && value <= 0x24f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x250) retVal[i] = 0x2c6f; // Single character else if (value == 0x251) retVal[i] = 0x2c6d; // Single character else if (value == 0x253) retVal[i] = 0x181; // Single character else if (value == 0x254) retVal[i] = 0x186; // Single character else if (value >= 0x256 && value <= 0x257) retVal[i] = value - 0xcd; // Alphabet else if (value == 0x259) retVal[i] = 0x18f; // Single character else if (value == 0x25b) retVal[i] = 0x190; // Single character else if (value == 0x260) retVal[i] = 0x193; // Single character else if (value == 0x263) retVal[i] = 0x194; // Single character else if (value == 0x268) retVal[i] = 0x197; // Single character else if (value == 0x269) retVal[i] = 0x196; // Single character else if (value == 0x26b) retVal[i] = 0x2c62; // Single character else if (value == 0x26f) retVal[i] = 0x19c; // Single character else if (value == 0x271) retVal[i] = 0x2c6e; // Single character else if (value == 0x272) retVal[i] = 0x19d; // Single character else if (value == 0x275) retVal[i] = 0x19f; // Single character else if (value == 0x27d) retVal[i] = 0x2c64; // Single character else if (value == 0x280) retVal[i] = 0x1a6; // Single character else if (value == 0x283) retVal[i] = 0x1a9; // Single character else if (value == 0x288) retVal[i] = 0x1ae; // Single character else if (value == 0x289) retVal[i] = 0x244; // Single character else if (value >= 0x28a && value <= 0x28b) retVal[i] = value - 0xd9; // Alphabet else if (value == 0x28c) retVal[i] = 0x245; // Single character else if (value == 0x292) retVal[i] = 0x1b7; // Single character else if (value == 0x345) retVal[i] = 0x399; // Single character else if (value >= 0x371 && value <= 0x373 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x377) retVal[i] = 0x376; // Single character else if (value >= 0x37b && value <= 0x37d) retVal[i] = value + 0x82; // Alphabet else if (value == 0x3ac) retVal[i] = 0x386; // Single character else if (value >= 0x3ad && value <= 0x3af) retVal[i] = value - 0x25; // Alphabet else if (value >= 0x3b1 && value <= 0x3c1) retVal[i] = value - 0x20; // Alphabet else if (value == 0x3c2) retVal[i] = 0x3a3; // Single character else if (value >= 0x3c3 && value <= 0x3cb) retVal[i] = value - 0x20; // Alphabet else if (value == 0x3cc) retVal[i] = 0x38c; // Single character else if (value >= 0x3cd && value <= 0x3ce) retVal[i] = value - 0x3f; // Alphabet else if (value == 0x3d0) retVal[i] = 0x392; // Single character else if (value == 0x3d1) retVal[i] = 0x398; // Single character else if (value == 0x3d5) retVal[i] = 0x3a6; // Single character else if (value == 0x3d6) retVal[i] = 0x3a0; // Single character else if (value == 0x3d7) retVal[i] = 0x3cf; // Single character else if (value >= 0x3d9 && value <= 0x3ef && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x3f0) retVal[i] = 0x39a; // Single character else if (value == 0x3f1) retVal[i] = 0x3a1; // Single character else if (value == 0x3f2) retVal[i] = 0x3f9; // Single character else if (value == 0x3f5) retVal[i] = 0x395; // Single character else if (value == 0x3f8) retVal[i] = 0x3f7; // Single character else if (value == 0x3fb) retVal[i] = 0x3fa; // Single character else if (value >= 0x430 && value <= 0x44f) retVal[i] = value - 0x20; // Alphabet else if (value >= 0x450 && value <= 0x45f) retVal[i] = value - 0x50; // Alphabet else if (value >= 0x461 && value <= 0x481 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x48b && value <= 0x4bf && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x4c2 && value <= 0x4ce && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x4cf) retVal[i] = 0x4c0; // Single character else if (value >= 0x4d1 && value <= 0x523 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x561 && value <= 0x586) retVal[i] = value - 0x30; // Alphabet else if (value == 0x1d79) retVal[i] = 0xa77d; // Single character else if (value == 0x1d7d) retVal[i] = 0x2c63; // Single character else if (value >= 0x1e01 && value <= 0x1e95 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x1e9b) retVal[i] = 0x1e60; // Single character else if (value >= 0x1ea1 && value <= 0x1eff && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x1f00 && value <= 0x1f07) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f10 && value <= 0x1f15) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f20 && value <= 0x1f27) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f30 && value <= 0x1f37) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f40 && value <= 0x1f45) retVal[i] = value + 0x8; // Alphabet else if (value == 0x1f51) retVal[i] = 0x1f59; // Single character else if (value == 0x1f53) retVal[i] = 0x1f5b; // Single character else if (value == 0x1f55) retVal[i] = 0x1f5d; // Single character else if (value == 0x1f57) retVal[i] = 0x1f5f; // Single character /* Work around stupid MSVC's limit on alternatives... * ---- * This is not generated automatically, but * needs to be inserted manually here. */ if (value >= 0x1f60 && value <= 0x1f67) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f70 && value <= 0x1f71) retVal[i] = value + 0x4a; // Alphabet else if (value >= 0x1f72 && value <= 0x1f75) retVal[i] = value + 0x56; // Alphabet else if (value >= 0x1f76 && value <= 0x1f77) retVal[i] = value + 0x64; // Alphabet else if (value >= 0x1f78 && value <= 0x1f79) retVal[i] = value + 0x80; // Alphabet else if (value >= 0x1f7a && value <= 0x1f7b) retVal[i] = value + 0x70; // Alphabet else if (value >= 0x1f7c && value <= 0x1f7d) retVal[i] = value + 0x7e; // Alphabet else if (value >= 0x1f80 && value <= 0x1f87) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1f90 && value <= 0x1f97) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1fa0 && value <= 0x1fa7) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1fb0 && value <= 0x1fb1) retVal[i] = value + 0x8; // Alphabet else if (value == 0x1fb3) retVal[i] = 0x1fbc; // Single character else if (value == 0x1fbe) retVal[i] = 0x399; // Single character else if (value == 0x1fc3) retVal[i] = 0x1fcc; // Single character else if (value >= 0x1fd0 && value <= 0x1fd1) retVal[i] = value + 0x8; // Alphabet else if (value >= 0x1fe0 && value <= 0x1fe1) retVal[i] = value + 0x8; // Alphabet else if (value == 0x1fe5) retVal[i] = 0x1fec; // Single character else if (value == 0x1ff3) retVal[i] = 0x1ffc; // Single character else if (value == 0x214e) retVal[i] = 0x2132; // Single character else if (value >= 0x2170 && value <= 0x217f) retVal[i] = value - 0x10; // Alphabet else if (value == 0x2184) retVal[i] = 0x2183; // Single character else if (value >= 0x24d0 && value <= 0x24e9) retVal[i] = value - 0x1a; // Alphabet else if (value >= 0x2c30 && value <= 0x2c5e) retVal[i] = value - 0x30; // Alphabet else if (value == 0x2c61) retVal[i] = 0x2c60; // Single character else if (value == 0x2c65) retVal[i] = 0x23a; // Single character else if (value == 0x2c66) retVal[i] = 0x23e; // Single character else if (value >= 0x2c68 && value <= 0x2c6c && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0x2c73) retVal[i] = 0x2c72; // Single character else if (value == 0x2c76) retVal[i] = 0x2c75; // Single character else if (value >= 0x2c81 && value <= 0x2ce3 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0x2d00 && value <= 0x2d25) retVal[i] = value - 0x1c60; // Alphabet else if (value >= 0xa641 && value <= 0xa65f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa663 && value <= 0xa66d && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa681 && value <= 0xa697 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa723 && value <= 0xa72f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa733 && value <= 0xa76f && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa77a && value <= 0xa77c && !(value & 1)) retVal[i] = value - 0x1; // Special letters else if (value >= 0xa77f && value <= 0xa787 && (value & 1)) retVal[i] = value - 0x1; // Special letters else if (value == 0xa78c) retVal[i] = 0xa78b; // Single character else if (value >= 0xff41 && value <= 0xff5a) retVal[i] = value - 0x20; // Alphabet } return retVal; } smooth-0.9.11~git20260403.0230c0da/classes/net/000077500000000000000000000000001516402577000202035ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/net/Makefile000066400000000000000000000006521516402577000216460ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options FOLDERS = protocols .PHONY: $(FOLDERS) all: $(FOLDERS) $(FOLDERS): + $(call makein,$@) clean: $(foreach FOLDER,$(FOLDERS),$(FOLDER)##clean) $(foreach FOLDER,$(FOLDERS),$(FOLDER)##clean): $(call cleanin,$(subst ##clean,,$@)) smooth-0.9.11~git20260403.0230c0da/classes/net/protocols/000077500000000000000000000000001516402577000222275ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/net/protocols/Makefile000066400000000000000000000011701516402577000236660ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifeq ($(USE_BUNDLED_LIBCURL),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support -DCURL_STATICLIB else ifneq ($(BUILD_OSX),True) MYCCOPTS += $(shell pkg-config --cflags libcurl) endif # Enter object files here: OBJECTS = file.o http.o protocol.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/net/protocols/file.cpp000077500000000000000000000042551516402577000236630ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include using namespace smooth::IO; S::Net::Protocols::Protocol *CreateProtocolFile(const S::String &iURL) { return new S::Net::Protocols::File(iURL); } S::Int protocolFileTmp = S::Net::Protocols::Protocol::AddProtocol(&CreateProtocolFile, L"file://"); S::Net::Protocols::File::File(const String &iURL) : Protocol(iURL) { } S::Net::Protocols::File::~File() { } S::Int S::Net::Protocols::File::DownloadToFile(const String &destination) { Bool error = True; String fileName = url.Tail(url.Length() - 7); if (url[7] == '/' && url[9] == ':' && url[10] == '/') fileName = url.Tail(url.Length() - 8); InStream in(STREAM_FILE, fileName, IS_READ); downloadProgress.Emit(0); downloadSpeed.Emit(NIL); if (in.GetLastError() == IO::IO_ERROR_OK) { Int bytes = in.Size(); if (bytes > 0) { OutStream out(STREAM_FILE, destination, OS_REPLACE); Buffer buffer(32768); Int startTicks = S::System::System::Clock(); Int percent = 0; for (Int i = 0; i < bytes; i += buffer.Size()) { Int amount = Math::Min(buffer.Size(), bytes - i); in.InputData(buffer, amount); out.OutputData(buffer, amount); if (Math::Round(1000.0 * i / bytes) != percent) { percent = Math::Round(1000.0 * i / bytes); downloadProgress.Emit(percent); downloadSpeed.Emit(String::FromInt(Math::Round((i / 1024) / (Float(S::System::System::Clock() - startTicks) / 1000))).Append(" kB/s")); } } } error = False; } downloadProgress.Emit(1000); if (!error) return Success(); else return Error(); } smooth-0.9.11~git20260403.0230c0da/classes/net/protocols/http.cpp000077500000000000000000000270421516402577000237220ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace smooth { namespace Net { namespace Protocols { size_t httpHeader(char *, size_t, size_t, void *); size_t httpWrite(char *, size_t, size_t, void *); int httpProgress(void *, double, double, double, double); }; }; }; S::Net::Protocols::Protocol *CreateProtocolHTTP(const S::String &iURL) { return new S::Net::Protocols::HTTP(iURL); } S::Int protocolHTTPTmp = S::Net::Protocols::Protocol::AddProtocol(&CreateProtocolHTTP, L"http://"); S::Int protocolHTTPSTmp = S::Net::Protocols::Protocol::AddProtocol(&CreateProtocolHTTP, L"https://"); S::Net::Protocols::HTTP::HTTP(const String &iURL) : Protocol(iURL) { mode = HTTP_METHOD_GET; proxyMode = HTTP_PROXY_NONE; proxyPort = 0; out = NIL; ulStart = 0; dlStart = 0; } S::Net::Protocols::HTTP::~HTTP() { } S::Int S::Net::Protocols::HTTP::SetHeaderField(const String &key, const String &value) { Parameter field; field.key = key; field.value = value; requestFields.Add(field); return Success(); } S::String S::Net::Protocols::HTTP::GetHeaderField(const String &key) const { foreach (const Parameter &field, requestFields) { if (field.key == key) return field.value; } return NIL; } S::Int S::Net::Protocols::HTTP::SetParameter(const String &key, const String &value) { Parameter parameter; parameter.key = key; parameter.value = value; requestParameters.Add(parameter); return Success(); } S::Int S::Net::Protocols::HTTP::SetParameterFile(const String &key, const String &fileName) { if (!S::File(fileName).Exists()) return Error(); Parameter parameter; parameter.key = key; parameter.value = fileName; parameter.isFile= True; requestParameters.Add(parameter); return Success(); } S::Int S::Net::Protocols::HTTP::SetMode(Short nMode) { mode = nMode; return Success(); } S::Int S::Net::Protocols::HTTP::SetContent(const String &nContent) { content = nContent; return Success(); } S::Int S::Net::Protocols::HTTP::SetProxy(const String &nProxy, Int nProxyPort) { proxy = nProxy; proxyPort = nProxyPort; if (proxyMode == HTTP_PROXY_NONE) proxyMode = HTTP_PROXY_HTTP; return Success(); } S::Int S::Net::Protocols::HTTP::SetProxyMode(Short nProxyMode) { proxyMode = nProxyMode; return Success(); } S::Int S::Net::Protocols::HTTP::SetProxyAuth(const String &nProxyUser, const String &nProxyPass) { proxyUser = nProxyUser; proxyPass = nProxyPass; return Success(); } S::String S::Net::Protocols::HTTP::GetResponseHeaderField(const String &key) const { foreach (const Parameter &field, responseFields) { if (field.key == key) return field.value; } return NIL; } S::Int S::Net::Protocols::HTTP::DownloadToFile(const String &fileName) { /* Create a cURL context. */ Bool error = False; CURL *curl = curl_easy_init(); if (!curl) return Error(); /* Set HTTP method. */ for (Int i = 0; i < requestParameters.Length(); i++) { if (requestParameters.GetNth(i).isFile) { mode = HTTP_METHOD_POST; break; } } if (content != NIL) mode = HTTP_METHOD_POST; if (mode == HTTP_METHOD_POST) curl_easy_setopt(curl, CURLOPT_POST, 1L); else if (mode == HTTP_METHOD_GET) curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); /* Set parameters. */ String url = this->url; curl_slist *headers = NULL; if (requestParameters.Length() > 0) { if (mode == HTTP_METHOD_GET) url.Append("?").Append(GetParametersURLEncoded()); else if (mode == HTTP_METHOD_POST) curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char *) GetParametersURLEncoded()); } /* Set headers. */ foreach (const Parameter &field, requestFields) headers = curl_slist_append(headers, String(field.key).Append(": ").Append(field.value)); /* Check to see if we are to transfer any files. */ Bool haveFiles = False; for (Int i = 0; i < requestParameters.Length(); i++) { if (requestParameters.GetNth(i).isFile) { haveFiles = True; break; } } /* Set content. */ Buffer postBuffer; if (content != NIL) { headers = curl_slist_append(headers, "Content-Type: text/plain; charset=UTF-8"); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char *) content.ConvertTo("UTF-8")); } else if (haveFiles) { String separator = "THIS_STRING_SEPARATES"; headers = curl_slist_append(headers, String("Content-Type: multipart/form-data; boundary=").Append(separator)); /* Write contents to temporary output file. */ Math::RandomSeed(); S::File tempFile = S::System::System::GetTempDirectory().Append("httprequest-").Append(Number((Int64) Math::Random() & 0x7FFFFFFF).ToHexString()).Append(".temp"); IO::OutStream out(IO::STREAM_FILE, tempFile, IO::OS_REPLACE); out.OutputString(String("--").Append(separator).Append("\r\n")); out.OutputString("Content-Disposition: form-data; name=\"MAX_FILE_SIZE\"\r\n\r\n"); out.OutputString("1000000\r\n"); foreach (const Parameter ¶meter, requestParameters) { out.OutputString(String("--").Append(separator).Append("\r\n")); if (!parameter.isFile) { out.OutputString(String("Content-Disposition: form-data; name=\"").Append(parameter.key).Append("\"\r\n\r\n")); out.OutputString(String(parameter.value).Append("\r\n")); } else { out.OutputString(String("Content-Disposition: form-data; name=\"").Append(parameter.key).Append("\"; filename=\"").Append(parameter.value).Append("\"\r\n\r\n")); IO::InStream in(IO::STREAM_FILE, parameter.value, IO::IS_READ); for (Int i = 0; i < in.Size(); i++) out.OutputNumber(in.InputNumber(1), 1); out.OutputString("\r\n"); } } out.OutputString(String("--").Append(separator).Append("--")); out.Close(); /* Read contents into buffer. */ IO::InStream in(IO::STREAM_FILE, tempFile, IO::IS_READ); postBuffer.Resize(in.Size()); for (Int i = 0; i < in.Size(); i++) postBuffer[i] = in.InputNumber(1); in.Close(); tempFile.Delete(); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postBuffer.Size()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char *) (UnsignedByte *) postBuffer); } /* Set URL and basic parameters. */ curl_easy_setopt(curl, CURLOPT_URL, (char *) url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); /* Set proxy information. */ if (proxyMode != HTTP_PROXY_NONE) { curl_easy_setopt(curl, CURLOPT_PROXY, (char *) proxy); curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxyPort); char *curlProxyUser = proxyUser != NIL ? curl_easy_escape(curl, proxyUser, 0) : NIL; char *curlProxyPass = proxyPass != NIL ? curl_easy_escape(curl, proxyPass, 0) : NIL; curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, (char *) String(curlProxyUser).Append(":").Append(curlProxyPass)); curl_free(curlProxyUser); curl_free(curlProxyPass); if (proxyMode == HTTP_PROXY_HTTP) curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); #if LIBCURL_VERSION_NUM >= 0x073400 else if (proxyMode == HTTP_PROXY_HTTPS) curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS); #endif #if LIBCURL_VERSION_NUM >= 0x071200 else if (proxyMode == HTTP_PROXY_SOCKS4) curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A); #else else if (proxyMode == HTTP_PROXY_SOCKS4) curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); #endif #if LIBCURL_VERSION_NUM >= 0x071200 else if (proxyMode == HTTP_PROXY_SOCKS5) curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); #else else if (proxyMode == HTTP_PROXY_SOCKS5) curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); #endif } /* Set callback functions. */ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &httpHeader); curl_easy_setopt(curl, CURLOPT_HEADERDATA, this); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &httpWrite); curl_easy_setopt(curl, CURLOPT_WRITEDATA, this); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &httpProgress); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this); /* Setup files and issue request. */ ulStart = 0; dlStart = 0; file = fileName; out = new IO::OutStream(IO::STREAM_FILE, fileName, IO::OS_REPLACE); if (curl_easy_perform(curl) != CURLE_OK) error = True; delete out; /* Clean up. */ curl_slist_free_all(headers); curl_easy_cleanup(curl); if (!error) return Success(); else return Error(); } S::String S::Net::Protocols::HTTP::GetParametersURLEncoded() const { String str; for (Int i = 0; i < requestParameters.Length(); i++) { const Parameter ¶meter = requestParameters.GetNth(i); if (i > 0) str.Append("&"); str.Append(parameter.key).Append("=").Append(parameter.value); } return str; } size_t S::Net::Protocols::httpHeader(char *buffer, size_t size, size_t n, void *data) { HTTP *http = (HTTP *) data; /* Cancel request if requested. */ if (http->doCancelDownload.Call()) return 0; /* Get data as string. */ String header; for (UnsignedInt i = 0; i < size * n; i++) header[i] = buffer[i]; /* Handle headers. */ if (header.StartsWith("HTTP/1.")) { /* Reset output stream when we get a new HTTP response. */ delete http->out; http->out = new IO::OutStream(IO::STREAM_FILE, http->file, IO::OS_REPLACE); http->responseFields.RemoveAll(); /* Add status code to header fields. */ Parameter field; field.key = "Status-Code"; field.value = header.Tail(header.Length() - header.Find(" ") - 1); http->responseFields.Add(field); } else if (header.Contains(": ")) { /* Split header into key and value. */ Parameter field; Int colon = header.Find(": "); field.key = header.Head(colon); field.value = header.Tail(header.Length() - colon - 2); http->responseFields.Add(field); } return size * n; } size_t S::Net::Protocols::httpWrite(char *buffer, size_t size, size_t n, void *data) { HTTP *http = (HTTP *) data; /* Cancel download if requested. */ if (http->doCancelDownload.Call()) return 0; /* Write data to output file. */ http->out->OutputData(buffer, size * n); return size * n; } int S::Net::Protocols::httpProgress(void *data, double dlTotal, double dlNow, double ulTotal, double ulNow) { HTTP *http = (HTTP *) data; if (ulNow > 0 && http->ulStart == 0) http->ulStart = System::System::Clock() - 1; if (dlNow > 0 && http->dlStart == 0) http->dlStart = System::System::Clock() - 1; if (http->dlStart == 0) { if (ulTotal > 0) http->uploadProgress.Emit(Math::Round(1000.0 * ulNow / ulTotal)); if (ulNow > 0) http->uploadSpeed.Emit(String::FromInt(Math::Round((ulNow / 1024) / (Float(System::System::Clock() - http->ulStart) / 1000))).Append(" kB/s")); } else { if (dlTotal > 0) http->downloadProgress.Emit(Math::Round(1000.0 * dlNow / dlTotal)); if (dlNow > 0) http->downloadSpeed.Emit(String::FromInt(Math::Round((dlNow / 1024) / (Float(System::System::Clock() - http->dlStart) / 1000))).Append(" kB/s")); } return 0; } smooth-0.9.11~git20260403.0230c0da/classes/net/protocols/protocol.cpp000077500000000000000000000051731516402577000246050ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include using namespace smooth::IO; S::Array *S::Net::Protocols::Protocol::protocol_creators = NIL; S::Array *S::Net::Protocols::Protocol::protocol_magics = NIL; S::Int addProtocolFreeTmp = S::AddFreeFunction(&S::Net::Protocols::Protocol::RemoveAllProtocols); S::Int S::Net::Protocols::Protocol::AddProtocol(Protocol *(*protocol)(const String &), const String &magic) { if (protocol == NIL) return Error(); if (protocol_creators == NIL) protocol_creators = new Array; if (protocol_magics == NIL) protocol_magics = new Array; protocol_creators->Add(protocol); protocol_magics->Add(magic); return Success(); } S::Int S::Net::Protocols::Protocol::RemoveAllProtocols() { protocol_creators->RemoveAll(); protocol_magics->RemoveAll(); delete protocol_creators; delete protocol_magics; return Success(); } S::Net::Protocols::Protocol *S::Net::Protocols::Protocol::CreateForURL(const String &url) { for (Int i = 0; i < protocol_creators->Length(); i++) { if (url.StartsWith(protocol_magics->GetNth(i))) return protocol_creators->GetNth(i)(url); } return NIL; } S::Net::Protocols::Protocol::Protocol(const String &iURL) { url = iURL; doCancelDownload.Connect(False); } S::Net::Protocols::Protocol::~Protocol() { } S::Int S::Net::Protocols::Protocol::DownloadToBuffer(Buffer &destination) { Math::RandomSeed(); S::File downloadFile = S::System::System::GetTempDirectory().Append("download-").Append(Number((Int64) Math::Random() & 0x7FFFFFFF).ToHexString()).Append(".temp"); Bool error = DownloadToFile(downloadFile); if (error) return Error(); InStream in(STREAM_FILE, downloadFile, IS_READ); Int size = in.Size(); destination.Resize(size); for (Int p = 0; p < size; p += 1024) in.InputData(destination + p, Math::Min(1024, size - p)); in.Close(); downloadFile.Delete(); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/system/000077500000000000000000000000001516402577000207415ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/system/Makefile000066400000000000000000000015621516402577000224050ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags x11) endif endif endif ifeq ($(USE_BUNDLED_LIBCPUID),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support -DLIBCPUID_DISABLE_DEPRECATED endif # Enter object files here: OBJECTS = console.o cpu.o dynamicloader.o event.o screen.o system.o timer.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,backends) CLEANCMD1 = $(call cleanin,backends) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/system/backends/000077500000000000000000000000001516402577000225135ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/system/backends/Makefile000066400000000000000000000013441516402577000241550ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = eventbackend.o screenbackend.o timerbackend.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,cocoa) && $(call makein,haiku) ALLCMD2 = $(call makein,posix) && $(call makein,threads) ALLCMD3 = $(call makein,win32) && $(call makein,xlib) CLEANCMD1 = $(call cleanin,cocoa) && $(call cleanin,haiku) CLEANCMD2 = $(call cleanin,posix) && $(call cleanin,threads) CLEANCMD3 = $(call cleanin,win32) && $(call cleanin,xlib) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/system/backends/cocoa/000077500000000000000000000000001516402577000235775ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/system/backends/cocoa/Makefile000066400000000000000000000007031516402577000252370ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_OSX),True) OBJECTS += eventcocoa.o screencocoa.o timercocoa.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/system/backends/cocoa/eventcocoa.mm000066400000000000000000000044221516402577000262620ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::System::EventBackend *CreateEventCocoa() { return new S::System::EventCocoa(); } S::Int eventCocoaTmp = S::System::EventBackend::SetBackend(&CreateEventCocoa); S::Bool S::System::EventCocoa::quitRequested = False; S::System::EventCocoa::EventCocoa() { type = EVENT_COCOA; } S::System::EventCocoa::~EventCocoa() { } S::Bool S::System::EventCocoa::ProcessNextEvent() { /* Run loop in main thread only. */ if (![NSThread isMainThread]) { S::System::System::Sleep(1); return True; } /* Try to find active modal windows. */ GUI::Window *smoothWindow = NIL; NSWindow *modalWindow = nil; for (Int n = GUI::Window::GetNOfWindows() - 1; n >= 0; n--) { GUI::Window *window = GUI::Window::GetNthWindow(n); if (window->IsVisible() && window->GetFlags() & GUI::WF_MODAL) { smoothWindow = window; modalWindow = (NSWindow *) window->GetSystemWindow(); break; } } /* The first loop invocation must not be modal * to prevent problems on macOS 10.9 Mavericks. */ static Bool ranNonModal = False; if (!ranNonModal) { ranNonModal = True; [NSApp run]; return True; } /* Run modal or regular loop. */ if (modalWindow != nil && [modalWindow isVisible]) { smoothWindow->EnterProtectedRegion(); [NSApp runModalForWindow: modalWindow]; smoothWindow->LeaveProtectedRegion(); } else { [NSApp run]; } /* Ask windows to close if quit has been requested. */ if (quitRequested) { quitRequested = False; for (Int n = GUI::Window::GetNOfWindows() - 1; n >= 0; n--) { GUI::Window *window = GUI::Window::GetNthWindow(n); if (window->IsVisible()) window->Close(); } } return True; } S::Void S::System::EventCocoa::RequestApplicationQuit() { quitRequested = True; } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/cocoa/screencocoa.mm000066400000000000000000000063751516402577000264310ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::System::ScreenBackend *CreateScreenCocoa() { return new S::System::ScreenCocoa(); } S::Int screenCocoaTmp = S::System::ScreenBackend::SetBackend(&CreateScreenCocoa); S::System::ScreenCocoa::ScreenCocoa() { type = SCREEN_COCOA; } S::System::ScreenCocoa::~ScreenCocoa() { } S::GUI::Rect S::System::ScreenCocoa::GetActiveScreenMetrics() { NSArray *screens = [NSScreen screens]; NSScreen *screen = nil; NSScreen *firstScreen = [screens objectAtIndex: 0]; if ([screens count] == 1) screen = firstScreen; else screen = ScreenFromPoint(Input::Pointer::GetPosition()); NSRect frame = [screen frame]; NSRect firstFrame = [firstScreen frame]; return GUI::Rect(GUI::Point(frame.origin.x, firstFrame.size.height - frame.origin.y - frame.size.height), GUI::Size(frame.size.width, frame.size.height)); } S::GUI::Rect S::System::ScreenCocoa::GetActiveScreenWorkArea() { NSArray *screens = [NSScreen screens]; NSScreen *screen = nil; NSScreen *firstScreen = [screens objectAtIndex: 0]; if ([screens count] == 1) screen = firstScreen; else screen = ScreenFromPoint(Input::Pointer::GetPosition()); NSRect frame = [screen visibleFrame]; NSRect firstFrame = [firstScreen frame]; return GUI::Rect(GUI::Point(frame.origin.x, firstFrame.size.height - frame.origin.y - frame.size.height), GUI::Size(frame.size.width, frame.size.height)); } S::GUI::Rect S::System::ScreenCocoa::GetVirtualScreenMetrics() { NSArray *screens = [NSScreen screens]; NSScreen *firstScreen = [screens objectAtIndex: 0]; NSRect firstFrame = [firstScreen frame]; GUI::Rect metrics; for (UnsignedInt i = 0; i < [screens count]; i++) { NSScreen *screen = [screens objectAtIndex: i]; NSRect frame = [screen frame]; metrics.left = Math::Min(metrics.left, frame.origin.x); metrics.top = Math::Min(metrics.top, firstFrame.size.height - frame.origin.y - frame.size.height); metrics.right = Math::Max(metrics.right, frame.origin.x + frame.size.width); metrics.bottom = Math::Max(metrics.bottom, firstFrame.size.height - frame.origin.y); } return metrics; } NSScreen *S::System::ScreenCocoa::ScreenFromPoint(const GUI::Point &point) { NSArray *screens = [NSScreen screens]; NSScreen *firstScreen = [screens objectAtIndex: 0]; NSRect firstFrame = [firstScreen frame]; for (UnsignedInt i = 0; i < [screens count]; i++) { NSScreen *screen = [screens objectAtIndex: i]; NSRect frame = [screen frame]; if (point.x >= frame.origin.x && point.x < frame.origin.x + frame.size.width && point.y >= firstFrame.size.height - frame.origin.y - frame.size.height && point.y < firstFrame.size.height - frame.origin.y ) return screen; } return nil; } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/cocoa/timercocoa.mm000066400000000000000000000036721516402577000262670ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::System::TimerBackend *CreateTimerCocoa(S::System::Timer *timer) { return new S::System::TimerCocoa(timer); } S::Int timerCocoaTmp = S::System::TimerBackend::SetBackend(&CreateTimerCocoa); @interface TimerCocoa : NSObject - (void) timerInvoked: (NSTimer *) theTimer; @end S::System::TimerCocoa::TimerCocoa(Timer *iTimer) : TimerBackend(iTimer) { type = TIMER_COCOA; timer = nil; receiver = [[::TimerCocoa alloc] init]; } S::System::TimerCocoa::~TimerCocoa() { Stop(); [(::TimerCocoa *) receiver release]; } S::Int S::System::TimerCocoa::Start(Int interval) { if (timer != nil) return Error(); timer = [NSTimer timerWithTimeInterval: interval / 1000.0 target: (id) receiver selector: @selector(timerInvoked:) userInfo: [NSNumber numberWithInt: thisTimer->GetHandle()] repeats: YES]; [[NSRunLoop mainRunLoop] addTimer: timer forMode: NSDefaultRunLoopMode]; return Success(); } S::Int S::System::TimerCocoa::Stop() { if (timer == nil) return Error(); [timer invalidate]; timer = nil; return Success(); } S::Int S::System::TimerCocoa::GetID() const { if (timer == nil) return Error(); return (Int64) timer; } @implementation TimerCocoa - (void) timerInvoked: (NSTimer *) theTimer { S::System::Timer *timer = (S::System::Timer *) S::Object::GetObject([[theTimer userInfo] intValue], S::System::Timer::classID); if (timer != NIL) timer->onInterval.Emit(); } @end smooth-0.9.11~git20260403.0230c0da/classes/system/backends/eventbackend.cpp000077500000000000000000000026151516402577000256570ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2017 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::System::EventBackend *CreateEventBackend() { return new S::System::EventBackend(); } S::System::EventBackend *(*S::System::EventBackend::backend_creator)() = &CreateEventBackend; S::Int S::System::EventBackend::SetBackend(EventBackend *(*backend)()) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::System::EventBackend *S::System::EventBackend::CreateBackendInstance() { return backend_creator(); } S::System::EventBackend::EventBackend() { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) EventWin32(); #endif type = EVENT_NONE; } S::System::EventBackend::~EventBackend() { } S::Short S::System::EventBackend::GetEventType() const { return type; } S::Bool S::System::EventBackend::ProcessNextEvent() { return False; } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/haiku/000077500000000000000000000000001516402577000236145ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/system/backends/haiku/Makefile000066400000000000000000000007051516402577000252560ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_HAIKU),True) OBJECTS += eventhaiku.o screenhaiku.o timerhaiku.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/system/backends/haiku/eventhaiku.cpp000066400000000000000000000075571516402577000265010ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include S::Int addEventHaikuInitTmp = S::AddInitFunction(&S::System::EventHaiku::Initialize); S::System::EventBackend *CreateEventHaiku() { return new S::System::EventHaiku(); } S::Int eventHaikuTmp = S::System::EventBackend::SetBackend(&CreateEventHaiku); S::Int S::System::EventHaiku::nested = 0; S::Array S::System::EventHaiku::messages; S::System::EventHaiku::EventHaiku() { type = EVENT_HAIKU; /* Deny timer interrupts outside of any event loops * to prevent interruption of sensitive code. */ if (!nested++) EventProcessor::denyTimerInterrupts.Call(); } S::System::EventHaiku::~EventHaiku() { /* Allow timer interrupts again before leaving the * outermost event processor. */ if (!--nested) EventProcessor::allowTimerInterrupts.Call(); } S::Int S::System::EventHaiku::Initialize() { messages.EnableLocking(); return Success(); } S::Void S::System::EventHaiku::EnqueueMessage(Void *window, const BMessage ¤tMessage, Int messageID, Int param1, Int param2) { messages.LockForWrite(); /* Process only the most recent B_MOUSE_MOVED message. */ if (messageID == B_MOUSE_MOVED) { foreachreverse (Message *message, messages) { if (message->window == window && message->messageID == messageID) { messages.RemoveNth(foreachindex); delete message; } } } /* Add new message to queue. */ Message *message = new Message(); message->window = window; message->currentMessage = currentMessage; message->messageID = messageID; message->param1 = param1; message->param2 = param2; messages.Add(message); messages.Unlock(); } S::Void S::System::EventHaiku::ProcessMessage(Void *window, const BMessage ¤tMessage, Int messageID, Int param1, Int param2) { EnqueueMessage(window, currentMessage, messageID, param1, param2); while (messages.Length() > 0) System::System::Sleep(0); } S::Bool S::System::EventHaiku::ProcessNextEvent() { /* Emulate a timeout of ~100ms by trying to find a message * 10 times while sleeping for 10ms between trying. */ for (Int i = 0; i < 10; i++) { /* Check for a message and process it. */ messages.LockForWrite(); if (messages.Length() > 0) { /* Get first message. */ Message *message = messages.GetFirst(); messages.RemoveNth(0); messages.Unlock(); if (message->messageID == B_TIMER) { /* Find timer and fire signal. */ Timer *timer = (Timer *) Object::GetObject(message->param1, Timer::classID); if (timer != NIL) timer->onInterval.Emit(); } else { /* Find window and process message. */ GUI::WindowHaiku *window = GUI::WindowHaiku::GetWindowBackend((BWindow *) message->window); if (window != NIL) window->ProcessSystemMessages(message->messageID, message->param1, message->param2, message->currentMessage); } delete message; break; } messages.Unlock(); /* Allow timeouts to be processed. */ EventProcessor::allowTimerInterrupts.Call(); /* Now sleep for 10ms. */ System::System::Sleep(10); /* Prevent timeouts from being processed. */ EventProcessor::denyTimerInterrupts.Call(); } return True; } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/haiku/screenhaiku.cpp000066400000000000000000000026661516402577000266330ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::System::ScreenBackend *CreateScreenHaiku() { return new S::System::ScreenHaiku(); } S::Int screenHaikuTmp = S::System::ScreenBackend::SetBackend(&CreateScreenHaiku); S::System::ScreenHaiku::ScreenHaiku() { type = SCREEN_HAIKU; } S::System::ScreenHaiku::~ScreenHaiku() { } S::GUI::Rect S::System::ScreenHaiku::GetActiveScreenMetrics() { BScreen screen; BRect frame = screen.Frame(); return GUI::Rect(GUI::Point(0, 0), GUI::Size(frame.right - frame.left + 1, frame.bottom - frame.top - 1)); } S::GUI::Rect S::System::ScreenHaiku::GetActiveScreenWorkArea() { BScreen screen; BRect frame = screen.Frame(); return GUI::Rect(GUI::Point(0, 0), GUI::Size(frame.right - frame.left + 1, frame.bottom - frame.top - 1)); } S::GUI::Rect S::System::ScreenHaiku::GetVirtualScreenMetrics() { BScreen screen; BRect frame = screen.Frame(); return GUI::Rect(GUI::Point(0, 0), GUI::Size(frame.right - frame.left + 1, frame.bottom - frame.top - 1)); } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/haiku/timerhaiku.cpp000066400000000000000000000064031516402577000264650ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include S::Int addTimerHaikuInitTmp = S::AddInitFunction(&S::System::TimerHaiku::Initialize); S::Int addTimerHaikuFreeTmp = S::AddFreeFunction(&S::System::TimerHaiku::Free); S::System::TimerBackend *CreateTimerHaiku(S::System::Timer *timer) { return new S::System::TimerHaiku(timer); } S::Int timerHaikuTmp = S::System::TimerBackend::SetBackend(&CreateTimerHaiku); S::System::TimerHaiku::TimerHaiku(Timer *iTimer) : TimerBackend(iTimer) { type = TIMER_HAIKU; timer = NIL; } S::System::TimerHaiku::~TimerHaiku() { Stop(); } S::Int S::System::TimerHaiku::Initialize() { EventProcessor::allowTimerInterrupts.Connect(&AllowTimerInterrupts); EventProcessor::denyTimerInterrupts.Connect(&DenyTimerInterrupts); return Success(); } S::Int S::System::TimerHaiku::Free() { EventProcessor::allowTimerInterrupts.Disconnect(&AllowTimerInterrupts); EventProcessor::denyTimerInterrupts.Disconnect(&DenyTimerInterrupts); return Success(); } S::Int S::System::TimerHaiku::AllowTimerInterrupts() { /* Unblock SIGALRM so timeouts can be processed. */ sigset_t ss; sigemptyset(&ss); sigaddset(&ss, SIGALRM); pthread_sigmask(SIG_UNBLOCK, &ss, NIL); return Success(); } S::Int S::System::TimerHaiku::DenyTimerInterrupts() { /* Block SIGALRM again. */ sigset_t ss; sigemptyset(&ss); sigaddset(&ss, SIGALRM); pthread_sigmask(SIG_BLOCK, &ss, NIL); return Success(); } S::Int S::System::TimerHaiku::Start(Int nInterval) { if (timer != NIL) return Error(); if (nInterval <= 0) nInterval = 1; timer = new timer_t; /* Set handler function. */ struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = TimerProc; sa.sa_flags = SA_SIGINFO; sigaction(SIGALRM, &sa, NIL); /* Create timer. */ struct sigevent se; memset(&se, 0, sizeof(se)); se.sigev_notify = SIGEV_SIGNAL; se.sigev_signo = SIGALRM; se.sigev_value.sival_int = thisTimer->GetHandle(); timer_create(CLOCK_REALTIME, &se, timer); /* Start timer. */ struct itimerspec ts; ts.it_value.tv_sec = nInterval / 1000; ts.it_value.tv_nsec = nInterval % 1000 * 1000000; ts.it_interval.tv_sec = nInterval / 1000; ts.it_interval.tv_nsec = nInterval % 1000 * 1000000; timer_settime(*timer, 0, &ts, NIL); return Success(); } S::Int S::System::TimerHaiku::Stop() { if (timer == NIL) return Error(); timer_delete(*timer); delete timer; timer = NIL; return Success(); } S::Int S::System::TimerHaiku::GetID() const { if (timer == NIL) return Error(); return (Int64) timer; } void S::System::TimerHaiku::TimerProc(int sig, siginfo_t *info, void *text) { System::EventHaiku::EnqueueMessage(0, BMessage(B_TIMER), B_TIMER, info->si_value.sival_int, 0); } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/posix/000077500000000000000000000000001516402577000236555ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/system/backends/posix/Makefile000066400000000000000000000006571516402577000253250ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_POSIXTIMER),True) OBJECTS += timerposix.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/system/backends/posix/timerposix.cpp000066400000000000000000000074241516402577000265730ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2025 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #if defined(__FreeBSD__) # include #endif #if defined(__linux__) && !defined(sigev_notify_thread_id) # define sigev_notify_thread_id _sigev_un._tid #endif S::Int addTimerPOSIXInitTmp = S::AddInitFunction(&S::System::TimerPOSIX::Initialize); S::Int addTimerPOSIXFreeTmp = S::AddFreeFunction(&S::System::TimerPOSIX::Free); S::System::TimerBackend *CreateTimerPOSIX(S::System::Timer *timer) { return new S::System::TimerPOSIX(timer); } S::Int timerPOSIXTmp = S::System::TimerBackend::SetBackend(&CreateTimerPOSIX); #if defined(__linux__) || defined(__FreeBSD__) pid_t S::System::TimerPOSIX::mainThreadID = 0; #endif S::System::TimerPOSIX::TimerPOSIX(Timer *iTimer) : TimerBackend(iTimer) { type = TIMER_POSIX; timer = NIL; } S::System::TimerPOSIX::~TimerPOSIX() { Stop(); } S::Int S::System::TimerPOSIX::Initialize() { EventProcessor::allowTimerInterrupts.Connect(&AllowTimerInterrupts); EventProcessor::denyTimerInterrupts.Connect(&DenyTimerInterrupts); #if defined(__linux__) mainThreadID = gettid(); #elif defined(__FreeBSD__) mainThreadID = pthread_getthreadid_np(); #endif return Success(); } S::Int S::System::TimerPOSIX::Free() { EventProcessor::allowTimerInterrupts.Disconnect(&AllowTimerInterrupts); EventProcessor::denyTimerInterrupts.Disconnect(&DenyTimerInterrupts); return Success(); } S::Int S::System::TimerPOSIX::AllowTimerInterrupts() { /* Unblock SIGALRM so timeouts can be processed. */ sigset_t ss; sigemptyset(&ss); sigaddset(&ss, SIGALRM); pthread_sigmask(SIG_UNBLOCK, &ss, NIL); return Success(); } S::Int S::System::TimerPOSIX::DenyTimerInterrupts() { /* Block SIGALRM again. */ sigset_t ss; sigemptyset(&ss); sigaddset(&ss, SIGALRM); pthread_sigmask(SIG_BLOCK, &ss, NIL); return Success(); } S::Int S::System::TimerPOSIX::Start(Int nInterval) { if (timer != NIL) return Error(); if (nInterval <= 0) nInterval = 1; timer = new timer_t; /* Set handler function. */ struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = TimerProc; sa.sa_flags = SA_SIGINFO; sigaction(SIGALRM, &sa, NIL); /* Create timer. */ struct sigevent se; memset(&se, 0, sizeof(se)); #if defined(__linux__) || defined(__FreeBSD__) se.sigev_notify = SIGEV_THREAD_ID; se.sigev_notify_thread_id = mainThreadID; #else se.sigev_notify = SIGEV_SIGNAL; #endif se.sigev_signo = SIGALRM; se.sigev_value.sival_int = thisTimer->GetHandle(); timer_create(CLOCK_REALTIME, &se, timer); /* Start timer. */ struct itimerspec ts; ts.it_value.tv_sec = nInterval / 1000; ts.it_value.tv_nsec = nInterval % 1000 * 1000000; ts.it_interval.tv_sec = nInterval / 1000; ts.it_interval.tv_nsec = nInterval % 1000 * 1000000; timer_settime(*timer, 0, &ts, NIL); return Success(); } S::Int S::System::TimerPOSIX::Stop() { if (timer == NIL) return Error(); timer_delete(*timer); delete timer; timer = NIL; return Success(); } S::Int S::System::TimerPOSIX::GetID() const { if (timer == NIL) return Error(); return (Int64) timer; } void S::System::TimerPOSIX::TimerProc(int sig, siginfo_t *info, void *text) { Timer *timer = (Timer *) Object::GetObject(info->si_value.sival_int, Timer::classID); if (timer != NIL) timer->onInterval.Emit(); } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/screenbackend.cpp000066400000000000000000000031511516402577000260060ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::System::ScreenBackend *CreateScreenBackend() { return new S::System::ScreenBackend(); } S::System::ScreenBackend *(*S::System::ScreenBackend::backend_creator)() = &CreateScreenBackend; S::Int S::System::ScreenBackend::SetBackend(ScreenBackend *(*backend)()) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::System::ScreenBackend *S::System::ScreenBackend::CreateBackendInstance() { return backend_creator(); } S::System::ScreenBackend::ScreenBackend() { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) ScreenWin32(); #endif type = SCREEN_NONE; } S::System::ScreenBackend::~ScreenBackend() { } S::Short S::System::ScreenBackend::GetScreenType() const { return type; } S::GUI::Rect S::System::ScreenBackend::GetActiveScreenMetrics() { return GUI::Rect(); } S::GUI::Rect S::System::ScreenBackend::GetActiveScreenWorkArea() { return GUI::Rect(); } S::GUI::Rect S::System::ScreenBackend::GetVirtualScreenMetrics() { return GUI::Rect(); } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/threads/000077500000000000000000000000001516402577000241455ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/system/backends/threads/Makefile000066400000000000000000000006631516402577000256120ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_THREADSTIMER),True) OBJECTS += timerthreads.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/system/backends/threads/timerthreads.cpp000077500000000000000000000072371516402577000273600ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2017 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include S::Int addTimerThreadsInitTmp = S::AddInitFunction(&S::System::TimerThreads::Initialize); S::Int addTimerThreadsFreeTmp = S::AddFreeFunction(&S::System::TimerThreads::Free); S::System::TimerBackend *CreateTimerThreads(S::System::Timer *timer) { return new S::System::TimerThreads(timer); } S::Int timerThreadsTmp = S::System::TimerBackend::SetBackend(&CreateTimerThreads); using namespace smooth::Threads; S::Threads::Mutex *S::System::TimerThreads::timerMutex = NIL; S::System::TimerThreads::TimerThreads(Timer *iTimer) : TimerBackend(iTimer) { type = TIMER_THREADS; thread = NIL; interval = 0; timeout = 0; cancel = False; } S::System::TimerThreads::~TimerThreads() { Stop(); } S::Int S::System::TimerThreads::Initialize() { timerMutex = new Mutex(); EventProcessor::allowTimerInterrupts.Connect(&AllowTimerInterrupts); EventProcessor::denyTimerInterrupts.Connect(&DenyTimerInterrupts); return Success(); } S::Int S::System::TimerThreads::Free() { EventProcessor::allowTimerInterrupts.Disconnect(&AllowTimerInterrupts); EventProcessor::denyTimerInterrupts.Disconnect(&DenyTimerInterrupts); delete timerMutex; return Success(); } S::Int S::System::TimerThreads::AllowTimerInterrupts() { /* Unlock mutex so timeouts can be processed. */ return timerMutex->Release(); } S::Int S::System::TimerThreads::DenyTimerInterrupts() { /* Lock mutex again. */ return timerMutex->Lock(); } S::Int S::System::TimerThreads::Start(Int nInterval) { if (nInterval <= 0) nInterval = 1; /* Cancel previous cancellation if * the thread is still running. */ if (cancel && thread->IsCurrentThread()) { cancel = False; interval = nInterval; timeout = System::System::Clock() + interval; return Success(); } if (thread != NIL) return Error(); interval = nInterval; timeout = System::System::Clock() + interval; thread = NonBlocking1(&TimerThreads::TimerProc, this).Call(thisTimer->GetHandle()); return Success(); } S::Int S::System::TimerThreads::Stop() { if (thread == NIL) return Error(); /* Check if the thread is already gone. */ if (thread->GetStatus() != THREAD_RUNNING) return Success(); /* Order the thread to cancel. */ if (!thread->IsCurrentThread()) { cancel = True; Bool lock = timerMutex->Release(); while (cancel == True) System::System::Sleep(0); if (lock) timerMutex->Lock(); } else { cancel = True; } return Success(); } S::Int S::System::TimerThreads::GetID() const { if (thread == NIL) return Error(); return (Int64) thread & 0xFFFFFFFF; } S::Int S::System::TimerThreads::TimerProc(Int handle) { while (!cancel) { if (System::System::Clock() >= timeout) { Timer *timer = (Timer *) Object::GetObject(handle, Timer::classID); if (timer == NIL) break; timerMutex->Lock(); timer->onInterval.Emit(); timerMutex->Release(); while (timeout <= System::System::Clock()) timeout += interval; } System::System::Sleep(1); } /* Reset thread variable and cancellation state. */ cancel = False; thread = NIL; return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/timerbackend.cpp000077500000000000000000000031641516402577000256560ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2010 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::System::TimerBackend *CreateTimerBackend(S::System::Timer *timer) { return new S::System::TimerBackend(timer); } S::System::TimerBackend *(*S::System::TimerBackend::backend_creator)(S::System::Timer *) = &CreateTimerBackend; S::Int S::System::TimerBackend::SetBackend(TimerBackend *(*backend)(Timer *)) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::System::TimerBackend *S::System::TimerBackend::CreateBackendInstance(Timer *timer) { return backend_creator(timer); } S::System::TimerBackend::TimerBackend(Timer *iTimer) { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) TimerWin32(); #endif type = TIMER_NONE; thisTimer = iTimer; } S::System::TimerBackend::~TimerBackend() { } S::Short S::System::TimerBackend::GetTimerType() const { return type; } S::Int S::System::TimerBackend::Start(Int interval) { return Error(); } S::Int S::System::TimerBackend::Stop() { return Error(); } S::Int S::System::TimerBackend::GetID() const { return -1; } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/win32/000077500000000000000000000000001516402577000234555ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/system/backends/win32/Makefile000066400000000000000000000007051516402577000251170ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_WIN32),True) OBJECTS += eventwin32.o screenwin32.o timerwin32.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/system/backends/win32/eventwin32.cpp000077500000000000000000000027421516402577000261750ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2017 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::System::EventBackend *CreateEventWin32() { return new S::System::EventWin32(); } S::Int eventWin32Tmp = S::System::EventBackend::SetBackend(&CreateEventWin32); S::System::EventWin32::EventWin32() { type = EVENT_WIN32; } S::System::EventWin32::~EventWin32() { } S::Bool S::System::EventWin32::ProcessNextEvent() { /* Look for and process a message or wait up * to 100ms if no message is available. */ MSG msg; if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { /* Process only the most recent WM_MOUSEMOVE message. */ if (msg.message == WM_MOUSEMOVE) { while (PeekMessage(&msg, msg.hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) { } } /* Translate and dispatch message. */ TranslateMessage(&msg); DispatchMessage(&msg); if (msg.message == WM_QUIT) return False; } else { /* Wait for a message up to 100ms. */ MsgWaitForMultipleObjects(0, NIL, False, 100, QS_ALLEVENTS); } return True; } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/win32/screenwin32.cpp000066400000000000000000000051121516402577000263220ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2014 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include S::System::ScreenBackend *CreateScreenWin32() { return new S::System::ScreenWin32(); } S::Int screenWin32Tmp = S::System::ScreenBackend::SetBackend(&CreateScreenWin32); S::System::ScreenWin32::ScreenWin32() { type = SCREEN_WIN32; } S::System::ScreenWin32::~ScreenWin32() { } S::GUI::Rect S::System::ScreenWin32::GetActiveScreenMetrics() { if (GetSystemMetrics(SM_CMONITORS) == 1) { return GUI::Rect(GUI::Point(0, 0), GUI::Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN))); } GUI::Point position = Input::Pointer::GetPosition(); POINT pos = { position.x, position.y }; HMONITOR monitor = MonitorFromPoint(pos, 2); MONITORINFO info; info.cbSize = sizeof(MONITORINFO); GetMonitorInfo(monitor, &info); return GUI::Rect(GUI::Point(info.rcMonitor.left, info.rcMonitor.top), GUI::Size(info.rcMonitor.right - info.rcMonitor.left, info.rcMonitor.bottom - info.rcMonitor.top)); } S::GUI::Rect S::System::ScreenWin32::GetActiveScreenWorkArea() { if (GetSystemMetrics(SM_CMONITORS) == 1) { RECT rect; SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); return GUI::Rect(GUI::Point(rect.left, rect.top), GUI::Size(rect.right - rect.left, rect.bottom - rect.top)); } GUI::Point position = Input::Pointer::GetPosition(); POINT pos = { position.x, position.y }; HMONITOR monitor = MonitorFromPoint(pos, 2); MONITORINFO info; info.cbSize = sizeof(MONITORINFO); GetMonitorInfo(monitor, &info); return GUI::Rect(GUI::Point(info.rcWork.left, info.rcWork.top), GUI::Size(info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top)); } S::GUI::Rect S::System::ScreenWin32::GetVirtualScreenMetrics() { if (GetSystemMetrics(SM_CMONITORS) == 1) { return GUI::Rect(GUI::Point(), GUI::Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN))); } return GUI::Rect(GUI::Point(GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN)), GUI::Size(GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN))); } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/win32/timerwin32.cpp000077500000000000000000000031761516402577000261760ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2010 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::System::TimerBackend *CreateTimerWin32(S::System::Timer *timer) { return new S::System::TimerWin32(timer); } S::Int timerWin32Tmp = S::System::TimerBackend::SetBackend(&CreateTimerWin32); S::Array S::System::TimerWin32::handles; S::System::TimerWin32::TimerWin32(Timer *timer) : TimerBackend(timer) { type = TIMER_WIN32; timerid = -1; } S::System::TimerWin32::~TimerWin32() { Stop(); } S::Int S::System::TimerWin32::Start(Int interval) { if (timerid != -1) return Error(); timerid = SetTimer(NIL, 0, interval, &TimerProc); handles.Add(thisTimer->GetHandle(), timerid); return Success(); } S::Int S::System::TimerWin32::Stop() { if (timerid == -1) return Error(); KillTimer(NIL, timerid); handles.Remove(timerid); timerid = -1; return Success(); } S::Int S::System::TimerWin32::GetID() const { if (timerid == -1) return Error(); return timerid; } void WINAPI S::System::TimerWin32::TimerProc(HWND wnd, UINT message, UINT_PTR timerid, DWORD time) { Timer *timer = (Timer *) Object::GetObject(handles.Get((Int) timerid), Timer::classID); if (timer != NIL) timer->onInterval.Emit(); } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/xlib/000077500000000000000000000000001516402577000234515ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/system/backends/xlib/Makefile000066400000000000000000000011661516402577000251150ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifneq ($(BUILD_WIN32),True) ifneq ($(BUILD_OSX),True) ifneq ($(BUILD_HAIKU),True) MYCCOPTS += $(shell pkg-config --cflags x11) endif endif endif # Enter object files here: OBJECTS = ifeq ($(BUILD_XLIB),True) OBJECTS += eventxlib.o screenxlib.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/system/backends/xlib/eventxlib.cpp000077500000000000000000000062741516402577000261710ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include using namespace X11; S::System::EventBackend *CreateEventXLib() { return new S::System::EventXLib(); } S::Int eventXLibTmp = S::System::EventBackend::SetBackend(&CreateEventXLib); S::Int S::System::EventXLib::nested = 0; S::System::EventXLib::EventXLib() { type = EVENT_XLIB; display = Backends::BackendXLib::GetDisplay(); /* Deny timer interrupts outside of any event loops * to prevent interruption of sensitive code. */ if (!nested++) EventProcessor::denyTimerInterrupts.Call(); } S::System::EventXLib::~EventXLib() { /* Allow timer interrupts again before leaving the * outermost event processor. */ if (!--nested) EventProcessor::allowTimerInterrupts.Call(); } /* Predicate function to find MotionNotify events. */ int FindMotionEvent(Display *d, XEvent *e, XPointer arg) { return (e->type == MotionNotify && e->xany.window == (X11::Window) arg); } /* Predicate function to find ConfigureNotify events. */ int FindConfigureEvent(Display *d, XEvent *e, XPointer arg) { return (e->type == ConfigureNotify && e->xany.window == (X11::Window) arg); } S::Bool S::System::EventXLib::ProcessNextEvent() { if (display == NIL) return False; /* Process events on main thread only. */ if (Threads::Thread::GetCurrentThreadID() != Threads::MainThreadID) { S::System::System::Sleep(1); return True; } /* Emulate a timeout of ~100ms by trying to find a message * 10 times while sleeping for 10ms between trying. */ for (Int i = 0; i < 10; i++) { /* XEventsQueued with QueuedAfterFlush sometimes hanged, * so we flush manually and use QueuedAfterReading then. */ XFlush(display); if (XEventsQueued(display, QueuedAfterReading)) { XEvent e; XNextEvent(display, &e); if (XFilterEvent(&e, None)) break; /* Process only the most recent MotionNotify and ConfigureNotify events. */ if (e.type == MotionNotify) while (XCheckIfEvent(display, &e, FindMotionEvent, (XPointer) e.xany.window)) { } if (e.type == ConfigureNotify) while (XCheckIfEvent(display, &e, FindConfigureEvent, (XPointer) e.xany.window)) { } /* Find window and dispatch event. */ GUI::WindowXLib *window = GUI::WindowXLib::GetWindowBackend(e.xany.window); if (window != NIL) window->ProcessSystemMessages(&e); break; } /* Allow timeouts to be processed. */ EventProcessor::allowTimerInterrupts.Call(); /* Now sleep for 10ms. */ System::System::Sleep(10); /* Prevent timeouts from being processed. */ EventProcessor::denyTimerInterrupts.Call(); } return True; } smooth-0.9.11~git20260403.0230c0da/classes/system/backends/xlib/screenxlib.cpp000066400000000000000000000107011516402577000263120ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include using namespace X11; S::System::ScreenBackend *CreateScreenXLib() { return new S::System::ScreenXLib(); } S::Int screenXLibTmp = S::System::ScreenBackend::SetBackend(&CreateScreenXLib); S::Int addScreenXLibInitTmp = S::AddInitFunction(&S::System::ScreenXLib::Initialize); S::Int addScreenXLibFreeTmp = S::AddFreeFunction(&S::System::ScreenXLib::Free); namespace X11 { # define Bool int typedef XID RROutput; struct XRRMonitorInfo { Atom name; Bool primary; Bool automatic; int noutput; int x; int y; int width; int height; int mwidth; int mheight; RROutput *outputs; }; static void *libXrandr = NIL; typedef XRRMonitorInfo * (*xrrgetmonitors_t)(Display *, Window, Bool, int *); typedef void (*xrrfreemonitors_t)(XRRMonitorInfo *); static xrrgetmonitors_t XRRGetMonitors = NIL; static xrrfreemonitors_t XRRFreeMonitors = NIL; # undef Bool }; namespace smooth { GUI::Rect MonitorRectFromPoint(Display *display, const GUI::Point &point) { if (XRRGetMonitors == NIL) return GUI::Rect(); GUI::Rect metrics; int monitorCount = 0; XRRMonitorInfo *monitors = XRRGetMonitors(display, DefaultRootWindow(display), True, &monitorCount); for (Int i = 0; i < monitorCount; i++) { if (point.x >= monitors[i].x && point.x < monitors[i].x + monitors[i].width && point.y >= monitors[i].y && point.y < monitors[i].y + monitors[i].height) metrics = GUI::Rect(GUI::Point(monitors[i].x, monitors[i].y), GUI::Size(monitors[i].width, monitors[i].height)); } XRRFreeMonitors(monitors); return metrics; } }; S::Int S::System::ScreenXLib::Initialize() { libXrandr = dlopen("libXrandr.so", RTLD_NOW | RTLD_LOCAL); if (libXrandr != NIL) { XRRGetMonitors = (xrrgetmonitors_t) dlsym(libXrandr, "XRRGetMonitors"); XRRFreeMonitors = (xrrfreemonitors_t) dlsym(libXrandr, "XRRFreeMonitors"); } return Success(); } S::Int S::System::ScreenXLib::Free() { if (libXrandr != NIL) dlclose(libXrandr); return Success(); } S::System::ScreenXLib::ScreenXLib() { type = SCREEN_XLIB; display = Backends::BackendXLib::GetDisplay(); } S::System::ScreenXLib::~ScreenXLib() { } S::GUI::Rect S::System::ScreenXLib::GetActiveScreenMetrics() { if (display == NIL) return GUI::Rect(); if (XRRGetMonitors != NIL) { GUI::Rect metrics = MonitorRectFromPoint(display, Input::Pointer::GetPosition()); if (metrics != GUI::Rect()) return metrics; } return GUI::Rect(GUI::Point(0, 0), GUI::Size(XWidthOfScreen(XDefaultScreenOfDisplay(display)), XHeightOfScreen(XDefaultScreenOfDisplay(display)))); } S::GUI::Rect S::System::ScreenXLib::GetActiveScreenWorkArea() { if (display == NIL) return GUI::Rect(); if (XRRGetMonitors != NIL) { GUI::Rect metrics = MonitorRectFromPoint(display, Input::Pointer::GetPosition()); if (metrics != GUI::Rect()) return metrics; } return GUI::Rect(GUI::Point(0, 0), GUI::Size(XWidthOfScreen(XDefaultScreenOfDisplay(display)), XHeightOfScreen(XDefaultScreenOfDisplay(display)))); } S::GUI::Rect S::System::ScreenXLib::GetVirtualScreenMetrics() { if (display == NIL) return GUI::Rect(); if (XRRGetMonitors != NIL) { GUI::Rect metrics; int monitorCount = 0; XRRMonitorInfo *monitors = XRRGetMonitors(display, DefaultRootWindow(display), True, &monitorCount); for (Int i = 0; i < monitorCount; i++) { metrics.left = Math::Min(metrics.left, monitors[i].x); metrics.top = Math::Min(metrics.top, monitors[i].y); metrics.right = Math::Max(metrics.right, monitors[i].x + monitors[i].width); metrics.bottom = Math::Max(metrics.bottom, monitors[i].y + monitors[i].height); } XRRFreeMonitors(monitors); if (monitorCount > 0) return metrics; } return GUI::Rect(GUI::Point(0, 0), GUI::Size(XWidthOfScreen(XDefaultScreenOfDisplay(display)), XHeightOfScreen(XDefaultScreenOfDisplay(display)))); } smooth-0.9.11~git20260403.0230c0da/classes/system/console.cpp000077500000000000000000000026631516402577000231210ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #if defined __WIN32__ # include #endif #include S::Int addConsoleInitTmp = S::AddInitFunction(&S::System::Console::Initialize); S::System::Console::Console() { } S::System::Console::Console(const Console &) { } S::Int S::System::Console::Initialize() { #if defined __WIN32__ SetConsoleOutputCP(CP_UTF8); #endif return Success(); } S::Int S::System::Console::SetTitle(const String &title) { #if defined __WIN32__ SetConsoleTitle(title); #endif return Success(); } S::Int S::System::Console::OutputString(const String &string) { #if defined __WIN32__ String::OutputFormat format("UTF-8"); #endif printf("%s", (char *) string); fflush(stdout); return Success(); } S::Int S::System::Console::OutputLine(const String &string) { #if defined __WIN32__ String::OutputFormat format("UTF-8"); #endif printf("%s\n", (char *) string); return Success(); } S::Void S::System::Console::WaitForKey() { getchar(); } smooth-0.9.11~git20260403.0230c0da/classes/system/cpu.cpp000077500000000000000000000112061516402577000222370ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2023 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::String S::System::CPU::vendorString; S::String S::System::CPU::brandString; S::Int S::System::CPU::numCores = 1; S::Int S::System::CPU::numLogicalCPUs = 1; S::Bool S::System::CPU::hasMMX = False; S::Bool S::System::CPU::hasMMXExt = False; S::Bool S::System::CPU::hasSSE = False; S::Bool S::System::CPU::hasSSE2 = False; S::Bool S::System::CPU::hasSSE3 = False; S::Bool S::System::CPU::hasSSSE3 = False; S::Bool S::System::CPU::hasSSE4_1 = False; S::Bool S::System::CPU::hasSSE4_2 = False; S::Bool S::System::CPU::hasSSE4a = False; S::Bool S::System::CPU::hasAVX = False; S::Bool S::System::CPU::hasAVX2 = False; S::Bool S::System::CPU::has3DNow = False; S::Bool S::System::CPU::has3DNowExt = False; S::Bool S::System::CPU::hasHT = False; S::Bool S::System::CPU::hasNX = False; S::Bool S::System::CPU::hasVMX = False; S::Bool S::System::CPU::hasSVM = False; S::System::CPU::CPU() { GetCPUID(); } S::Errors::Error S::System::CPU::GetCPUID() const { static Bool initialized = False; static Bool failed = False; /* Return if we are already initialized or failed before. */ if (initialized) return Success(); if (failed) return Error(); /* Find total number of CPUs if CPUID is not available. */ if (!cpuid_present()) { /* Set to initialized and get number of CPUs. */ initialized = True; numCores = cpuid_get_total_cpus(); numLogicalCPUs = numCores; #if defined __APPLE__ && defined __aarch64__ /* Apple uses an HMP architecture with power efficient cores * showing performance characteristics similar to threads in * an SMT system. We assume there are 4 power efficient cores * and treat them the same way as SMT threads. */ if (numCores >= 6) numCores -= 4; #endif return Success(); } /* Get actual CPUID data. */ cpu_raw_data_array_t raw; system_id_t system; failed = True; if (cpuid_get_all_raw_data(&raw) < 0) return Error(); if (cpu_identify_all(&raw, &system) < 0) return Error(); /* OK, set to initialized. */ initialized = True; failed = False; /* Set vendor and brand strings. */ cpu_id_t& data = system.cpu_types[0]; vendorString = data.vendor_str; brandString = data.brand_str; if (brandString == NIL) brandString = data.cpu_codename; /* Find number of cores and logical CPUs per processor. */ numCores = 0; numLogicalCPUs = 0; for (Int i = 0; i < system.num_cpu_types; i++) { numCores += system.cpu_types[i].num_cores; numLogicalCPUs += system.cpu_types[i].num_logical_cpus; } /* Find number of processors and mutiply core numbers. */ Int numTotalCPUs = cpuid_get_total_cpus(); Int numProcessors = numTotalCPUs / numLogicalCPUs; numCores *= numProcessors; numLogicalCPUs *= numProcessors; /* Set feature flags. */ hasMMX = data.flags[CPU_FEATURE_MMX]; hasMMXExt = data.flags[CPU_FEATURE_MMXEXT]; hasSSE = data.flags[CPU_FEATURE_SSE]; hasSSE2 = data.flags[CPU_FEATURE_SSE2]; hasSSE3 = data.flags[CPU_FEATURE_PNI]; hasSSSE3 = data.flags[CPU_FEATURE_SSSE3]; hasSSE4_1 = data.flags[CPU_FEATURE_SSE4_1]; hasSSE4_2 = data.flags[CPU_FEATURE_SSE4_2]; hasSSE4a = data.flags[CPU_FEATURE_SSE4A]; hasAVX = data.flags[CPU_FEATURE_AVX]; hasAVX2 = data.flags[CPU_FEATURE_AVX2]; has3DNow = data.flags[CPU_FEATURE_3DNOW]; has3DNowExt = data.flags[CPU_FEATURE_3DNOWEXT]; hasHT = data.flags[CPU_FEATURE_HT]; hasNX = data.flags[CPU_FEATURE_NX]; hasVMX = data.flags[CPU_FEATURE_VMX]; hasSVM = data.flags[CPU_FEATURE_SVM]; /* Free CPUID data. */ cpuid_free_system_id(&system); cpuid_free_raw_data_array(&raw); return Success(); } S::System::Endianness S::System::CPU::GetEndianness() const { UnsignedInt32 value; UnsignedInt8 *buffer = (UnsignedInt8 *) &value; buffer[0] = 0x00; buffer[1] = 0x01; buffer[2] = 0x02; buffer[3] = 0x03; if (value == 0x00010203) return EndianBig; else if (value == 0x03020100) return EndianLittle; return EndianUnknown; } S::Int S::System::CPU::MeasureClock(Int ms) const { /* Measure CPU clock. */ return cpu_clock_measure(ms, 1); } smooth-0.9.11~git20260403.0230c0da/classes/system/dynamicloader.cpp000077500000000000000000000153151516402577000242700ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #ifdef __linux__ # include #endif #ifdef __WIN32__ # include #else # include # include #endif const S::Short S::System::DynamicLoader::classID = S::Object::RequestClassID(); S::System::DynamicLoader::DynamicLoader(const String &module) : handle(NIL) { #if defined __WIN32__ static String dllExt = ".dll"; static String versionPattern = dllExt; #elif defined __APPLE__ static String dllExt = ".dylib"; static String versionPattern = String(".*").Append(dllExt); #else static String dllExt = ".so"; static String versionPattern = String(dllExt).Append(".*"); #endif #ifdef __WIN32__ if (module[1] != ':') { /* Try the supplied module name in application directory. */ handle = LoadLibrary(GUI::Application::GetApplicationDirectory().Append(module).Append(module.EndsWith(dllExt) ? String() : dllExt)); } if (handle == NIL) { /* Try the supplied module name system wide. */ handle = LoadLibrary(String(module).Append(module.EndsWith(dllExt) ? String() : dllExt)); } #else Int dlopenFlags = RTLD_NOW | RTLD_LOCAL; #if defined __FreeBSD__ || defined __NetBSD__ dlopenFlags |= RTLD_NODELETE; #endif if (!module.StartsWith("/")) { /* Try the supplied module name in application directory. */ handle = dlopen(GUI::Application::GetApplicationDirectory().Append(module).Append(module.EndsWith(dllExt) || module.Contains(String(dllExt).Append(".")) ? String() : dllExt), dlopenFlags); } if (handle == NIL) { /* Try the supplied module name system wide. */ handle = dlopen(String(module).Append(module.EndsWith(dllExt) || module.Contains(String(dllExt).Append(".")) ? String() : dllExt), dlopenFlags); } if (handle == NIL) { const Array &directories = GetLibraryDirectories(); /* Try loading an unversioned library. */ foreach (const String &path, directories) { Directory directory(path); const Array &files = directory.GetFilesByPattern(String(module.StartsWith("lib") || module.Contains("/") ? String() : "lib").Append(module).Append(module.EndsWith(dllExt) || module.Contains(String(dllExt).Append(".")) ? String() : dllExt)); if (files.Length() > 0) { handle = dlopen((String) files.GetFirst(), dlopenFlags); } if (handle != NIL) return; } /* Try loading a versioned library. */ foreach (const String &path, directories) { Directory directory(path); const Array &files = directory.GetFilesByPattern(String(module.StartsWith("lib") || module.Contains("/") ? String() : "lib").Append(module).Append(module.EndsWith(dllExt) || module.Contains(String(dllExt).Append(".")) ? String() : versionPattern)); if (files.Length() > 0) { handle = dlopen((String) files.GetFirst(), dlopenFlags); } if (handle != NIL) return; } } #endif } S::System::DynamicLoader::~DynamicLoader() { #ifdef __WIN32__ if (handle != NIL) FreeLibrary((HINSTANCE) handle); #else #if defined __OpenBSD__ || defined __HAIKU__ /* OpenBSD and Haiku do not support RTLD_NODELETE yet, * so we cannot close .so files without risking a crash. */ #else if (handle != NIL) dlclose(handle); #endif #endif } S::Void *S::System::DynamicLoader::GetFunctionAddress(const String &functionName) const { if (handle == NIL) return NIL; #ifdef __WIN32__ return (Void *) GetProcAddress((HINSTANCE) handle, functionName); #else return (Void *) dlsym(handle, functionName); #endif } S::Void *S::System::DynamicLoader::GetSystemModuleHandle() const { return handle; } const S::Array &S::System::DynamicLoader::GetLibraryDirectories() { static Array directories; #ifndef __WIN32__ if (directories.Length() == 0) { /* Look for /usr/lib and /usr/local/lib on all systems. */ if (Directory("/usr/lib").Exists()) directories.Add("/usr/lib"); if (Directory("/usr/local/lib").Exists()) directories.Add("/usr/local/lib"); #if defined __APPLE__ /* Look for library directories of ports projects. */ if (Directory("/opt/local/lib").Exists()) directories.Add("/opt/local/lib"); if (Directory("/sw/lib").Exists()) directories.Add("/sw/lib"); #elif defined __linux__ /* Query X11 library path to handle architecture-specific library paths on Linux. */ Dl_info info = { 0 }; dladdr((void *) &X11::XOpenDisplay, &info); const String libraryPath = File(info.dli_fname).GetFilePath(); directories.Add(libraryPath); #elif defined __HAIKU__ /* Query smooth library path to handle architecture suffix on Haiku. */ Dl_info info = { 0 }; dladdr((void *) &S::System::DynamicLoader::GetLibraryDirectories, &info); const String libraryPath = File(info.dli_fname).GetFilePath(); directories.Add(libraryPath); if (libraryPath.Contains("/system/non-packaged/")) directories.Add(libraryPath.Replace("/system/non-packaged/", "/system/")); else if (libraryPath.Contains("/system/")) directories.Add(libraryPath.Replace("/system/", "/system/non-packaged/")); #elif defined __NetBSD__ /* Packages live in /usr/pkg on NetBSD. */ if (Directory("/usr/pkg/lib").Exists()) directories.Add("/usr/pkg/lib"); #endif /* Parse /etc/ld.so.conf if it exists. */ if (File("/etc/ld.so.conf").Exists()) ParseDirectoryList("/etc/ld.so.conf", directories); /* Parse LD_LIBRARY_PATH environment variable. */ const Array &paths = String(getenv("LD_LIBRARY_PATH")).Explode(":"); foreach (const String &path, paths) if (Directory(path).Exists()) directories.Add(path); } #endif return directories; } S::Void S::System::DynamicLoader::ParseDirectoryList(const String &pattern, Array &directories) { #ifndef __WIN32__ Directory directory(File(pattern).GetFilePath()); const Array &files = directory.GetFilesByPattern(File(pattern).GetFileName()); foreach (const File &file, files) { IO::InStream in(IO::STREAM_FILE, file); while (in.GetPos() < in.Size()) { String line = in.InputLine(); if (line == NIL) continue; else if (line.StartsWith("#")) continue; else if (line.StartsWith("include ")) ParseDirectoryList(line.Tail(line.Length() - 8), directories); else directories.Add(line); } } #endif } smooth-0.9.11~git20260403.0230c0da/classes/system/event.cpp000066400000000000000000000021431516402577000225660ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::Callback0 S::System::EventProcessor::allowTimerInterrupts; S::Callback0 S::System::EventProcessor::denyTimerInterrupts; S::System::EventProcessor::EventProcessor() { backend = EventBackend::CreateBackendInstance(); } S::System::EventProcessor::~EventProcessor() { delete backend; } S::Bool S::System::EventProcessor::ProcessNextEvent() { Int suspendCount = GUI::Application::Lock::SuspendLock(); Bool result = backend->ProcessNextEvent(); GUI::Application::Lock::ResumeLock(suspendCount); return result; } smooth-0.9.11~git20260403.0230c0da/classes/system/screen.cpp000066400000000000000000000025161516402577000227300ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::Int addScreenInitTmp = S::AddInitFunction(&S::System::Screen::Initialize); S::Int addScreenFreeTmp = S::AddFreeFunction(&S::System::Screen::Free); S::System::ScreenBackend *S::System::Screen::backend = NIL; S::System::Screen::Screen() { } S::System::Screen::Screen(const Screen &) { } S::Int S::System::Screen::Initialize() { backend = ScreenBackend::CreateBackendInstance(); return Success(); } S::Int S::System::Screen::Free() { delete backend; return Success(); } S::GUI::Rect S::System::Screen::GetActiveScreenMetrics() { return backend->GetActiveScreenMetrics(); } S::GUI::Rect S::System::Screen::GetActiveScreenWorkArea() { return backend->GetActiveScreenWorkArea(); } S::GUI::Rect S::System::Screen::GetVirtualScreenMetrics() { return backend->GetVirtualScreenMetrics(); } smooth-0.9.11~git20260403.0230c0da/classes/system/system.cpp000066400000000000000000000406621516402577000230010ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifdef __APPLE__ # include # include #endif #include #include #include #include #include #ifdef __WIN32__ # include # include # include # include #else # include # include # include # include # include # include # include #endif S::Int S::System::System::nextGUID = 0; S::System::System::System() { } S::System::System::System(const System &) { } S::Int S::System::System::RequestGUID() { return nextGUID++; } S::String S::System::System::GetVersionString() { return SMOOTH_VERSION; } S::String S::System::System::GetAPIVersion() { return SMOOTH_APIVERSION; } S::UnsignedInt64 S::System::System::Clock() { #ifdef __WIN32__ static LARGE_INTEGER frequency; static BOOL useQPC = QueryPerformanceFrequency(&frequency); if (useQPC) { LARGE_INTEGER count; QueryPerformanceCounter(&count); return count.QuadPart / (frequency.QuadPart / 1000); } return clock() * UnsignedInt64(1000) / CLOCKS_PER_SEC; #else timeval tv; gettimeofday(&tv, NIL); return tv.tv_sec * UnsignedInt64(1000) + tv.tv_usec / 1000; #endif } S::Bool S::System::System::Sleep(UnsignedInt mSeconds) { #ifdef __WIN32__ ::Sleep(mSeconds); #else timespec req; timespec rem; req.tv_sec = mSeconds / 1000; req.tv_nsec = (mSeconds % 1000) * 1000000; while (nanosleep(&req, &rem) == -1) { if (errno != EINTR) break; req.tv_sec = rem.tv_sec; req.tv_nsec = rem.tv_nsec; } #endif return True; } S::Void S::System::System::Reboot() { #ifdef __WIN32__ /* Acquire shutdown privilege. */ LUID value; TOKEN_PRIVILEGES token; HANDLE htoken; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &htoken); LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &value); token.PrivilegeCount = 1; token.Privileges[0].Luid = value; token.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(htoken, false, &token, 0, NULL, NULL); /* Reboot system. */ ExitWindowsEx(EWX_REBOOT | EWX_FORCEIFHUNG, 0); #elif defined __APPLE__ static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess }; /* Send restart message to system process. */ AEAddressDesc targetDesc; AppleEvent eventReply = { typeNull, NULL }; AppleEvent appleEventToSend = { typeNull, NULL }; AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess, sizeof(kPSNOfSystemProcess), &targetDesc); AECreateAppleEvent(kCoreEventClass, kAERestart, &targetDesc, kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend); AESend(&appleEventToSend, &eventReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, NULL, NULL); AEDisposeDesc(&eventReply); AEDisposeDesc(&appleEventToSend); AEDisposeDesc(&targetDesc); #else /* Try rebooting using D-Bus messages to ConsoleKit and systemd-logind. */ if (!fork()) { execl("/bin/sh", "sh", "-c", "dbus-send --system --dest=\"org.freedesktop.ConsoleKit\" /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Restart", NULL); exit(0); } if (!fork()) { execl("/bin/sh", "sh", "-c", "dbus-send --system --dest=\"org.freedesktop.login1\" /org/freedesktop/login1 org.freedesktop.login1.Manager.Reboot boolean:true", NULL); exit(0); } /* Try rebooting using the shutdown command. */ if (!fork()) { execl("/bin/sh", "sh", "-c", "shutdown -r now", NULL); exit(0); } #endif } S::Void S::System::System::Shutdown() { #if defined __WIN32__ /* Acquire shutdown privilege. */ LUID value; TOKEN_PRIVILEGES token; HANDLE htoken; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &htoken); LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &value); token.PrivilegeCount = 1; token.Privileges[0].Luid = value; token.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(htoken, false, &token, 0, NULL, NULL); /* Shutdown system. */ ExitWindowsEx(EWX_POWEROFF | EWX_FORCEIFHUNG, 0); #elif defined __APPLE__ static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess }; /* Send shutdown message to system process. */ AEAddressDesc targetDesc; AppleEvent eventReply = { typeNull, NULL }; AppleEvent appleEventToSend = { typeNull, NULL }; AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess, sizeof(kPSNOfSystemProcess), &targetDesc); AECreateAppleEvent(kCoreEventClass, kAEShutDown, &targetDesc, kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend); AESend(&appleEventToSend, &eventReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, NULL, NULL); AEDisposeDesc(&eventReply); AEDisposeDesc(&appleEventToSend); AEDisposeDesc(&targetDesc); #else /* Try shutting down using D-Bus messages to ConsoleKit and systemd-logind. */ if (!fork()) { execl("/bin/sh", "sh", "-c", "dbus-send --system --dest=\"org.freedesktop.ConsoleKit\" /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Stop", NULL); exit(0); } if (!fork()) { execl("/bin/sh", "sh", "-c", "dbus-send --system --dest=\"org.freedesktop.login1\" /org/freedesktop/login1 org.freedesktop.login1.Manager.PowerOff boolean:true", NULL); exit(0); } /* Try shutting down using the shutdown command. */ # if defined __linux__ || defined __GNU__ if (!fork()) { execl("/bin/sh", "sh", "-c", "shutdown -P now", NULL); exit(0); } # elif defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ if (!fork()) { execl("/bin/sh", "sh", "-c", "shutdown -p now", NULL); exit(0); } # else if (!fork()) { execl("/bin/sh", "sh", "-c", "shutdown -h now", NULL); exit(0); } # endif #endif } S::Bool S::System::System::OpenURL(const String &url) { #if defined __WIN32__ ShellExecute(NULL, (wchar_t *) L"open", url, NULL, NULL, SW_SHOW); #elif defined __APPLE__ const char *args = url; if (!fork()) { execl("/usr/bin/open", "open", args, NULL); exit(0); } #elif defined __HAIKU__ const char *args = url; if (!fork()) { execl("/boot/system/bin/open", "open", args, NULL); exit(0); } #else /* Try the open commands from freedesktop.org and the Gnome, KDE * and Xfce desktops first, then try some widely used browsers. */ static const char *browsers[] = { "xdg-open", "gnome-open", "kde-open", "exo-open", "firefox", "safari", "chrome", "opera", "mozilla", "netscape", "epiphany", "konqueror", NIL }; String command; for (int i = 0; browsers[i] != NIL; i++) { if (i > 0) command.Append(" || "); command.Append(browsers[i]).Append(" \"").Append(url).Append("\""); } const char *cmd = command; if (!fork()) { execl("/bin/sh", "sh", "-c", cmd, NULL); exit(0); } #endif return True; } S::String S::System::System::GetWindowsRootDirectory() { static String windowsDir; if (windowsDir != NIL) return windowsDir; #ifdef __WIN32__ Buffer buffer(32768 + 1); GetWindowsDirectory(buffer, buffer.Size()); windowsDir = buffer; #endif if (!windowsDir.EndsWith(Directory::GetDirectoryDelimiter())) windowsDir.Append(Directory::GetDirectoryDelimiter()); if ( windowsDir == Directory::GetDirectoryDelimiter()) windowsDir = NIL; return windowsDir; } S::String S::System::System::GetProgramFilesDirectory() { static String programsDir; if (programsDir != NIL) return programsDir; #ifdef __WIN32__ HKEY currentVersion; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion", 0, KEY_QUERY_VALUE, ¤tVersion) == ERROR_SUCCESS) { DWORD size = (32768 + 1) * sizeof(wchar_t); Buffer buffer(size); RegQueryValueEx(currentVersion, L"ProgramFilesDir", 0, NIL, buffer, &size); programsDir = (wchar_t *) (BYTE *) buffer; RegCloseKey(currentVersion); } if (programsDir == NIL) { /* Failed to get the program files directory from the registry. * Get the directory name from the environment variable. */ Buffer buffer(32768 + 1); ExpandEnvironmentStrings(String("%ProgramFiles%"), buffer, buffer.Size()); programsDir = buffer; } #endif if (!programsDir.EndsWith(Directory::GetDirectoryDelimiter())) programsDir.Append(Directory::GetDirectoryDelimiter()); if ( programsDir == Directory::GetDirectoryDelimiter()) programsDir = NIL; return programsDir; } S::String S::System::System::GetApplicationDataDirectory() { static String configDir; if (configDir != NIL) return configDir; String::InputFormat inputFormat("UTF-8"); #if defined __WIN32__ ITEMIDLIST *idlist; Buffer buffer(32768 + 1); SHGetSpecialFolderLocation(NIL, CSIDL_APPDATA, &idlist); SHGetPathFromIDList(idlist, buffer); configDir = buffer; CoTaskMemFree(idlist); #elif defined __APPLE__ passwd *pw = getpwuid(getuid()); if (pw != NIL) configDir = pw->pw_dir; else configDir = "~"; configDir = configDir.Append("/Library/Preferences"); #elif defined __HAIKU__ FILE *pstdin = popen("finddir B_USER_SETTINGS_DIRECTORY", "r"); Buffer buffer(PATH_MAX + 1); buffer.Zero(); fscanf(pstdin, String("%[^\n]").Append(String::FromInt(buffer.Size() - 1)), (char *) buffer); pclose(pstdin); configDir = buffer; #else configDir = getenv("XDG_CONFIG_HOME"); if (configDir == NIL) { passwd *pw = getpwuid(getuid()); if (pw != NIL) configDir = pw->pw_dir; else configDir = "~"; configDir = configDir.Append("/.config"); } #endif if (!configDir.EndsWith(Directory::GetDirectoryDelimiter())) configDir.Append(Directory::GetDirectoryDelimiter()); if ( configDir == Directory::GetDirectoryDelimiter()) configDir = NIL; return configDir; } S::String S::System::System::GetApplicationCacheDirectory() { static String cacheDir; if (cacheDir != NIL) return cacheDir; String::InputFormat inputFormat("UTF-8"); #if defined __WIN32__ ITEMIDLIST *idlist; Buffer buffer(32768 + 1); SHGetSpecialFolderLocation(NIL, CSIDL_APPDATA, &idlist); SHGetPathFromIDList(idlist, buffer); cacheDir = buffer; CoTaskMemFree(idlist); #elif defined __APPLE__ passwd *pw = getpwuid(getuid()); if (pw != NIL) cacheDir = pw->pw_dir; else cacheDir = "~"; cacheDir = cacheDir.Append("/Library/Caches"); #elif defined __HAIKU__ FILE *pstdin = popen("finddir B_USER_CACHE_DIRECTORY", "r"); Buffer buffer(PATH_MAX + 1); buffer.Zero(); fscanf(pstdin, String("%[^\n]").Append(String::FromInt(buffer.Size() - 1)), (char *) buffer); pclose(pstdin); cacheDir = buffer; #else cacheDir = getenv("XDG_CACHE_HOME"); if (cacheDir == NIL) { passwd *pw = getpwuid(getuid()); if (pw != NIL) cacheDir = pw->pw_dir; else cacheDir = "~"; cacheDir = cacheDir.Append("/.cache"); } #endif if (!cacheDir.EndsWith(Directory::GetDirectoryDelimiter())) cacheDir.Append(Directory::GetDirectoryDelimiter()); if ( cacheDir == Directory::GetDirectoryDelimiter()) cacheDir = NIL; return cacheDir; } S::String S::System::System::GetPersonalFilesDirectory(PersonalFilesType type) { static String personalDir[NumPersonalFilesTypes]; if (personalDir[type] != NIL) return personalDir[type]; String::InputFormat inputFormat("UTF-8"); #ifdef __WIN32__ ITEMIDLIST *idlist; Buffer buffer(32768 + 1); switch (type) { default: case PersonalFilesGeneric: SHGetSpecialFolderLocation(NIL, CSIDL_PROFILE, &idlist); break; case PersonalFilesDocuments: SHGetSpecialFolderLocation(NIL, CSIDL_PERSONAL, &idlist); break; case PersonalFilesPictures: SHGetSpecialFolderLocation(NIL, CSIDL_MYPICTURES, &idlist); break; case PersonalFilesMusic: SHGetSpecialFolderLocation(NIL, CSIDL_MYMUSIC, &idlist); break; case PersonalFilesMovies: if (Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 5, 1)) SHGetSpecialFolderLocation(NIL, CSIDL_MYVIDEO, &idlist); else SHGetSpecialFolderLocation(NIL, CSIDL_PERSONAL, &idlist); break; case PersonalFilesDownloads: SHGetSpecialFolderLocation(NIL, CSIDL_PERSONAL, &idlist); break; } SHGetPathFromIDList(idlist, buffer); personalDir[type] = buffer; CoTaskMemFree(idlist); if (personalDir[type] == NIL) personalDir[type] = "C:"; #else passwd *pw = getpwuid(getuid()); if (pw != NIL) personalDir[type] = pw->pw_dir; else personalDir[type] = "~"; #ifdef __APPLE__ OSErr error = -1; FSRef entry; switch (type) { default: case PersonalFilesGeneric: break; case PersonalFilesDocuments: error = FSFindFolder(kUserDomain, kDocumentsFolderType, kDontCreateFolder, &entry); break; case PersonalFilesPictures: error = FSFindFolder(kUserDomain, kPictureDocumentsFolderType, kDontCreateFolder, &entry); break; case PersonalFilesMusic: error = FSFindFolder(kUserDomain, kMusicDocumentsFolderType, kDontCreateFolder, &entry); break; case PersonalFilesMovies: error = FSFindFolder(kUserDomain, kMovieDocumentsFolderType, kDontCreateFolder, &entry); break; case PersonalFilesDownloads: break; } if (error == noErr) { CFURLRef url = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &entry); if (url != NIL) { CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); if (path != NIL) { Buffer buffer(CFStringGetLength(path) * 4 + 1); CFStringGetCString(path, buffer, buffer.Size(), kCFStringEncodingUTF8); personalDir[type] = buffer; CFRelease(path); } CFRelease(url); } } #else String configHome = getenv("XDG_CONFIG_HOME"); if (configHome == NIL) configHome = String(personalDir[type]).Append("/.config"); if (File(String(configHome).Append("/user-dirs.dirs")).Exists()) { IO::InStream in(IO::STREAM_FILE, String(configHome).Append("/user-dirs.dirs"), IO::IS_READ); while (in.GetPos() < in.Size()) { String entry = in.InputLine(); if ((type == PersonalFilesDocuments && entry.StartsWith("XDG_DOCUMENTS_DIR")) || (type == PersonalFilesPictures && entry.StartsWith("XDG_PICTURES_DIR" )) || (type == PersonalFilesMusic && entry.StartsWith("XDG_MUSIC_DIR" )) || (type == PersonalFilesMovies && entry.StartsWith("XDG_VIDEOS_DIR" )) || (type == PersonalFilesDownloads && entry.StartsWith("XDG_DOWNLOAD_DIR" ))) { personalDir[type] = entry.SubString(entry.Find("\"") + 1, entry.FindLast("\"") - entry.Find("\"") - 1).Replace("$HOME", personalDir[type]); break; } } } #endif #endif if (!personalDir[type].EndsWith(Directory::GetDirectoryDelimiter())) personalDir[type].Append(Directory::GetDirectoryDelimiter()); if ( personalDir[type] == Directory::GetDirectoryDelimiter()) personalDir[type] = NIL; return personalDir[type]; } S::String S::System::System::GetResourcesDirectory() { static String resourcesDir; if (resourcesDir != NIL) return resourcesDir; resourcesDir = GUI::Application::GetApplicationDirectory(); #if !defined __WIN32__ resourcesDir[resourcesDir.Length() - 1] = 0; resourcesDir[resourcesDir.FindLast(Directory::GetDirectoryDelimiter()) + 1] = 0; #if defined __HAIKU__ resourcesDir.Append("data"); #else resourcesDir.Append("share"); #endif if (!Directory(resourcesDir).Exists()) resourcesDir = GUI::Application::GetApplicationDirectory(); #endif if (!resourcesDir.EndsWith(Directory::GetDirectoryDelimiter())) resourcesDir.Append(Directory::GetDirectoryDelimiter()); if ( resourcesDir == Directory::GetDirectoryDelimiter()) resourcesDir = NIL; return resourcesDir; } S::String S::System::System::GetTempDirectory() { static String tempDir; if (tempDir != NIL) return tempDir; String::InputFormat inputFormat("UTF-8"); #if defined __WIN32__ Buffer buffer(32768 + 1); GetTempPath(buffer.Size(), buffer); tempDir = buffer; #elif defined __HAIKU__ FILE *pstdin = popen("finddir B_COMMON_TEMP_DIRECTORY", "r"); Buffer buffer(PATH_MAX + 1); buffer.Zero(); fscanf(pstdin, String("%[^\n]").Append(String::FromInt(buffer.Size() - 1)), (char *) buffer); pclose(pstdin); tempDir = buffer; #else tempDir = getenv("TMPDIR"); if (tempDir == NIL) tempDir = "/var/tmp"; #endif if (!tempDir.EndsWith(Directory::GetDirectoryDelimiter())) tempDir.Append(Directory::GetDirectoryDelimiter()); if ( tempDir == Directory::GetDirectoryDelimiter()) tempDir = NIL; return tempDir; } smooth-0.9.11~git20260403.0230c0da/classes/system/timer.cpp000066400000000000000000000027301516402577000225670ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2010 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include const S::Short S::System::Timer::classID = S::Object::RequestClassID(); S::System::Timer::Timer() { backend = TimerBackend::CreateBackendInstance(this); type = classID; interval = 0; status = TIMER_STOPPED; onInterval.SetParentObject(this); } S::System::Timer::~Timer() { Stop(); delete backend; } S::Int S::System::Timer::Start(Int iInterval) { if (status == TIMER_RUNNING) return Error(); interval = iInterval; status = TIMER_RUNNING; return backend->Start(interval); } S::Int S::System::Timer::Stop() { if (status != TIMER_RUNNING) return Error(); status = TIMER_STOPPED; return backend->Stop(); } S::Int S::System::Timer::Restart(Int iInterval) { if (status != TIMER_RUNNING) return Error(); Stop(); return Start(interval); } S::Int S::System::Timer::GetID() const { return backend->GetID(); } S::Int S::System::Timer::GetInterval() const { return interval; } S::Short S::System::Timer::GetStatus() const { return status; } smooth-0.9.11~git20260403.0230c0da/classes/threads/000077500000000000000000000000001516402577000210475ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/threads/Makefile000066400000000000000000000007151516402577000225120ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. # Enter object files here: OBJECTS = access.o mutex.o rwlock.o semaphore.o thread.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,backends) CLEANCMD1 = $(call cleanin,backends) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/threads/access.cpp000066400000000000000000000045761516402577000230300ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2015 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::Threads::Mutex *S::Threads::Access::mutex = NIL; S::Int addAccessInitTmp = S::AddInitFunction(&S::Threads::Access::Initialize); S::Int addAccessFreeTmp = S::AddFreeFunction(&S::Threads::Access::Free); S::Int S::Threads::Access::Initialize() { mutex = new Mutex(); return Success(); } S::Int S::Threads::Access::Free() { delete mutex; mutex = NIL; return Success(); } S::Bool S::Threads::Access::Value(volatile Bool &value) { if (mutex != NIL) mutex->Lock(); Bool result = value; if (mutex != NIL) mutex->Release(); return result; } S::Bool S::Threads::Access::Set(volatile Bool &value, Bool n) { mutex->Lock(); Bool result = value = n; mutex->Release(); return result; } S::Short S::Threads::Access::Value(volatile Short &value) { if (mutex != NIL) mutex->Lock(); Short result = value; if (mutex != NIL) mutex->Release(); return result; } S::Short S::Threads::Access::Increment(volatile Short &value) { mutex->Lock(); Short result = ++value; mutex->Release(); return result; } S::Short S::Threads::Access::Decrement(volatile Short &value) { mutex->Lock(); Short result = --value; mutex->Release(); return result; } S::Short S::Threads::Access::Set(volatile Short &value, Short n) { mutex->Lock(); Short result = value = n; mutex->Release(); return result; } S::Int S::Threads::Access::Value(volatile Int &value) { mutex->Lock(); Int result = value; mutex->Release(); return result; } S::Int S::Threads::Access::Increment(volatile Int &value) { mutex->Lock(); Int result = ++value; mutex->Release(); return result; } S::Int S::Threads::Access::Decrement(volatile Int &value) { mutex->Lock(); Int result = --value; mutex->Release(); return result; } S::Int S::Threads::Access::Set(volatile Int &value, Int n) { mutex->Lock(); Int result = value = n; mutex->Release(); return result; } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/000077500000000000000000000000001516402577000226215ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/Makefile000066400000000000000000000011231516402577000242560ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = mutexbackend.o semaphorebackend.o threadbackend.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,cocoa) ALLCMD2 = $(call makein,posix) ALLCMD3 = $(call makein,win32) CLEANCMD1 = $(call cleanin,cocoa) CLEANCMD2 = $(call cleanin,posix) CLEANCMD3 = $(call cleanin,win32) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/cocoa/000077500000000000000000000000001516402577000237055ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/cocoa/Makefile000066400000000000000000000006511516402577000253470ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_OSX),True) OBJECTS += threadcocoa.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/cocoa/threadcocoa.mm000066400000000000000000000064351516402577000265240ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::Threads::ThreadBackend *CreateThreadCocoa(S::Void *iThread) { return new S::Threads::ThreadCocoa(iThread); } S::Int threadCocoaTmp = S::Threads::ThreadBackend::SetBackend(&CreateThreadCocoa); S::Threads::ThreadCocoa::ThreadCocoa(Void *iThread) { pthread_mutex_init(&mutex, NIL); type = THREAD_COCOA; thread = NIL; myThread = False; info.threadProc = NIL; info.threadParam = NIL; if (iThread != NIL) thread = (pthread_t *) iThread; } S::Threads::ThreadCocoa::~ThreadCocoa() { if (myThread) Stop(); pthread_mutex_destroy(&mutex); } S::Int S::Threads::ThreadCocoa::Start(Void (*threadProc)(Void *), Void *threadParam) { Stop(); info.threadProc = threadProc; info.threadParam = threadParam; thread = new pthread_t; myThread = True; /* Get process stack size in order to use it for created threads. * Otherwise, the default stack size on macOS is only 512 kB which * may be too small for some deeply recursive calls. */ rlimit limit; getrlimit(RLIMIT_STACK, &limit); /* Set stack size to process stack size value and create thread. */ pthread_attr_t attributes; pthread_attr_init(&attributes); if (limit.rlim_cur >= PTHREAD_STACK_MIN && limit.rlim_cur != RLIM_INFINITY) pthread_attr_setstacksize(&attributes, limit.rlim_cur); pthread_create(thread, &attributes, Caller, &info); pthread_attr_destroy(&attributes); return Success(); } S::Int S::Threads::ThreadCocoa::Stop() { pthread_mutex_lock(&mutex); if (thread == NIL || pthread_equal(pthread_self(), *thread)) { pthread_mutex_unlock(&mutex); return Error(); } pthread_t *thread = this->thread; Bool myThread = this->myThread; this->thread = NIL; pthread_mutex_unlock(&mutex); pthread_cancel(*thread); pthread_detach(*thread); if (myThread) delete thread; return Success(); } S::Int S::Threads::ThreadCocoa::Wait() { pthread_mutex_lock(&mutex); if (thread == NIL || pthread_equal(pthread_self(), *thread)) { pthread_mutex_unlock(&mutex); return Error(); } pthread_t *thread = this->thread; Bool myThread = this->myThread; this->thread = NIL; pthread_mutex_unlock(&mutex); pthread_join(*thread, NIL); if (myThread) delete thread; return Success(); } S::Void S::Threads::ThreadCocoa::Exit() { pthread_mutex_lock(&mutex); if (thread == NIL || !pthread_equal(pthread_self(), *thread)) { pthread_mutex_unlock(&mutex); return; } pthread_t *thread = this->thread; Bool myThread = this->myThread; this->thread = NIL; pthread_mutex_unlock(&mutex); pthread_detach(*thread); if (myThread) delete thread; } void *S::Threads::ThreadCocoa::Caller(void *param) { ThreadInfo *info = (ThreadInfo *) param; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; info->threadProc(info->threadParam); [pool release]; return NULL; } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/mutexbackend.cpp000077500000000000000000000032341516402577000260040ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::Threads::MutexBackend *CreateMutexBackend(S::Void *iMutex) { return new S::Threads::MutexBackend(iMutex); } S::Threads::MutexBackend *(*S::Threads::MutexBackend::backend_creator)(S::Void *) = &CreateMutexBackend; S::Int S::Threads::MutexBackend::SetBackend(MutexBackend *(*backend)(Void *)) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::Threads::MutexBackend *S::Threads::MutexBackend::CreateBackendInstance(Void *iMutex) { return backend_creator(iMutex); } S::Threads::MutexBackend::MutexBackend(Void *iMutex) { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) MutexWin32(); #endif type = MUTEX_NONE; } S::Threads::MutexBackend::~MutexBackend() { } S::Short S::Threads::MutexBackend::GetMutexType() const { return type; } S::Void *S::Threads::MutexBackend::GetSystemMutex() const { return NIL; } S::Bool S::Threads::MutexBackend::Lock() { return False; } S::Bool S::Threads::MutexBackend::TryLock() { return False; } S::Bool S::Threads::MutexBackend::Release() { return False; } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/posix/000077500000000000000000000000001516402577000237635ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/posix/Makefile000066400000000000000000000007751516402577000254340ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_POSIXTHREADS),True) OBJECTS += mutexposix.o semaphoreposix.o ifneq ($(BUILD_OSX),True) OBJECTS += threadposix.o endif endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/posix/mutexposix.cpp000077500000000000000000000033741516402577000267260ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Threads::MutexBackend *CreateMutexPOSIX(S::Void *iMutex) { return new S::Threads::MutexPOSIX(iMutex); } S::Int mutexPOSIXTmp = S::Threads::MutexBackend::SetBackend(&CreateMutexPOSIX); S::Threads::MutexPOSIX::MutexPOSIX(Void *iMutex) { type = MUTEX_POSIX; if (iMutex != NIL) { mutex = (pthread_mutex_t *) iMutex; myMutex = False; } else { mutex = new pthread_mutex_t; myMutex = True; pthread_mutexattr_t mutexattr; pthread_mutexattr_init(&mutexattr); pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); if (pthread_mutex_init(mutex, &mutexattr) != 0) { delete mutex; mutex = NIL; } pthread_mutexattr_destroy(&mutexattr); } } S::Threads::MutexPOSIX::~MutexPOSIX() { if (myMutex && mutex != NIL) { pthread_mutex_destroy(mutex); delete mutex; } } S::Void *S::Threads::MutexPOSIX::GetSystemMutex() const { return (Void *) mutex; } S::Bool S::Threads::MutexPOSIX::Lock() { if (mutex != NIL && pthread_mutex_lock(mutex) == 0) return True; return False; } S::Bool S::Threads::MutexPOSIX::TryLock() { if (mutex != NIL && pthread_mutex_trylock(mutex) == 0) return True; return False; } S::Bool S::Threads::MutexPOSIX::Release() { if (mutex != NIL && pthread_mutex_unlock(mutex) == 0) return True; return False; } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/posix/semaphoreposix.cpp000077500000000000000000000050761516402577000275500ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Threads::SemaphoreBackend *CreateSemaphorePOSIX(S::Int iValue, S::Void *iSemaphore) { return new S::Threads::SemaphorePOSIX(iValue, iSemaphore); } S::Int semaphorePOSIXTmp = S::Threads::SemaphoreBackend::SetBackend(&CreateSemaphorePOSIX); S::Threads::SemaphorePOSIX::SemaphorePOSIX(Int iValue, Void *iSemaphore) : SemaphoreBackend(iValue) { type = SEMAPHORE_POSIX; if (iSemaphore != NIL) { SemaphorePOSIX *oSemaphore = (SemaphorePOSIX *) iSemaphore; mutex = oSemaphore->mutex; condition = oSemaphore->condition; count = oSemaphore->count; max = oSemaphore->max; mySemaphore = False; } else { mutex = new pthread_mutex_t; condition = new pthread_cond_t; count = iValue; max = iValue; mySemaphore = True; if (pthread_mutex_init(mutex, NIL) != 0) { delete mutex; delete condition; mutex = NIL; condition = NIL; } else if (pthread_cond_init(condition, NIL) != 0) { pthread_mutex_destroy(mutex); delete mutex; delete condition; mutex = NIL; condition = NIL; } } } S::Threads::SemaphorePOSIX::~SemaphorePOSIX() { if (mySemaphore && mutex != NIL) { pthread_mutex_destroy(mutex); pthread_cond_destroy(condition); delete mutex; delete condition; } } S::Void *S::Threads::SemaphorePOSIX::GetSystemSemaphore() const { return (Void *) this; } S::Bool S::Threads::SemaphorePOSIX::Wait() { if (mutex == NIL) return False; pthread_mutex_lock(mutex); while (count <= 0) pthread_cond_wait(condition, mutex); count -= 1; pthread_mutex_unlock(mutex); return True; } S::Bool S::Threads::SemaphorePOSIX::TryWait() { if (mutex == NIL) return False; pthread_mutex_lock(mutex); if (count > 0) { count -= 1; pthread_mutex_unlock(mutex); return True; } pthread_mutex_unlock(mutex); return False; } S::Bool S::Threads::SemaphorePOSIX::Release() { if (mutex == NIL) return False; pthread_mutex_lock(mutex); if (count < max) { count += 1; pthread_cond_signal(condition); pthread_mutex_unlock(mutex); return True; } pthread_mutex_unlock(mutex); return False; } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/posix/threadposix.cpp000077500000000000000000000051761516402577000270350ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Threads::ThreadBackend *CreateThreadPOSIX(S::Void *iThread) { return new S::Threads::ThreadPOSIX(iThread); } S::Int threadPOSIXTmp = S::Threads::ThreadBackend::SetBackend(&CreateThreadPOSIX); S::Threads::ThreadPOSIX::ThreadPOSIX(Void *iThread) { pthread_mutex_init(&mutex, NIL); type = THREAD_POSIX; thread = NIL; myThread = False; info.threadProc = NIL; info.threadParam = NIL; if (iThread != NIL) thread = (pthread_t *) iThread; } S::Threads::ThreadPOSIX::~ThreadPOSIX() { if (myThread) Stop(); pthread_mutex_destroy(&mutex); } S::Int S::Threads::ThreadPOSIX::Start(Void (*threadProc)(Void *), Void *threadParam) { Stop(); info.threadProc = threadProc; info.threadParam = threadParam; thread = new pthread_t; myThread = True; pthread_create(thread, NULL, Caller, &info); return Success(); } S::Int S::Threads::ThreadPOSIX::Stop() { pthread_mutex_lock(&mutex); if (thread == NIL || pthread_equal(pthread_self(), *thread)) { pthread_mutex_unlock(&mutex); return Error(); } pthread_t *thread = this->thread; Bool myThread = this->myThread; this->thread = NIL; pthread_mutex_unlock(&mutex); pthread_cancel(*thread); pthread_detach(*thread); if (myThread) delete thread; return Success(); } S::Int S::Threads::ThreadPOSIX::Wait() { pthread_mutex_lock(&mutex); if (thread == NIL || pthread_equal(pthread_self(), *thread)) { pthread_mutex_unlock(&mutex); return Error(); } pthread_t *thread = this->thread; Bool myThread = this->myThread; this->thread = NIL; pthread_mutex_unlock(&mutex); pthread_join(*thread, NIL); if (myThread) delete thread; return Success(); } S::Void S::Threads::ThreadPOSIX::Exit() { pthread_mutex_lock(&mutex); if (thread == NIL || !pthread_equal(pthread_self(), *thread)) { pthread_mutex_unlock(&mutex); return; } pthread_t *thread = this->thread; Bool myThread = this->myThread; this->thread = NIL; pthread_mutex_unlock(&mutex); pthread_detach(*thread); if (myThread) delete thread; } void *S::Threads::ThreadPOSIX::Caller(void *param) { ThreadInfo *info = (ThreadInfo *) param; info->threadProc(info->threadParam); return NULL; } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/semaphorebackend.cpp000077500000000000000000000035521516402577000266300ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::Threads::SemaphoreBackend *CreateSemaphoreBackend(S::Int iValue, S::Void *iSemaphore) { return new S::Threads::SemaphoreBackend(iValue, iSemaphore); } S::Threads::SemaphoreBackend *(*S::Threads::SemaphoreBackend::backend_creator)(S::Int, S::Void *) = &CreateSemaphoreBackend; S::Int S::Threads::SemaphoreBackend::SetBackend(SemaphoreBackend *(*backend)(Int, Void *)) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::Threads::SemaphoreBackend *S::Threads::SemaphoreBackend::CreateBackendInstance(Int iValue, Void *iSemaphore) { return backend_creator(iValue, iSemaphore); } S::Threads::SemaphoreBackend::SemaphoreBackend(Int iValue, Void *iSemaphore) { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) SemaphoreWin32(iValue, iSemaphore); #endif type = SEMAPHORE_NONE; } S::Threads::SemaphoreBackend::~SemaphoreBackend() { } S::Short S::Threads::SemaphoreBackend::GetSemaphoreType() const { return type; } S::Void *S::Threads::SemaphoreBackend::GetSystemSemaphore() const { return NIL; } S::Bool S::Threads::SemaphoreBackend::Wait() { return False; } S::Bool S::Threads::SemaphoreBackend::TryWait() { return False; } S::Bool S::Threads::SemaphoreBackend::Release() { return False; } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/threadbackend.cpp000077500000000000000000000033061516402577000261110ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #if defined __WIN32__ && defined SMOOTH_STATIC #include #endif S::Threads::ThreadBackend *CreateThreadBackend(S::Void *iThread) { return new S::Threads::ThreadBackend(iThread); } S::Threads::ThreadBackend *(*S::Threads::ThreadBackend::backend_creator)(S::Void *) = &CreateThreadBackend; S::Int S::Threads::ThreadBackend::SetBackend(ThreadBackend *(*backend)(Void *)) { if (backend == NIL) return Error(); backend_creator = backend; return Success(); } S::Threads::ThreadBackend *S::Threads::ThreadBackend::CreateBackendInstance(Void *iThread) { return backend_creator(iThread); } S::Threads::ThreadBackend::ThreadBackend(Void *iThread) { #if defined __WIN32__ && defined SMOOTH_STATIC volatile Bool null = 0; if (null) ThreadWin32(); #endif type = THREAD_NONE; } S::Threads::ThreadBackend::~ThreadBackend() { } S::Short S::Threads::ThreadBackend::GetThreadType() const { return type; } S::Int S::Threads::ThreadBackend::Start(Void (*threadProc)(Void *), Void *threadParam) { return Error(); } S::Int S::Threads::ThreadBackend::Stop() { return Error(); } S::Int S::Threads::ThreadBackend::Wait() { return Error(); } S::Void S::Threads::ThreadBackend::Exit() { } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/win32/000077500000000000000000000000001516402577000235635ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/win32/Makefile000066400000000000000000000007111516402577000252220ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Enter object files here: OBJECTS = ifeq ($(BUILD_WIN32),True) OBJECTS += mutexwin32.o semaphorewin32.o threadwin32.o endif ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/win32/mutexwin32.cpp000077500000000000000000000026421516402577000263230ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Threads::MutexBackend *CreateMutexWin32(S::Void *iMutex) { return new S::Threads::MutexWin32(iMutex); } S::Int mutexWin32Tmp = S::Threads::MutexBackend::SetBackend(&CreateMutexWin32); S::Threads::MutexWin32::MutexWin32(Void *iMutex) { type = MUTEX_WIN32; if (iMutex != NIL) { mutex = (CRITICAL_SECTION *) iMutex; myMutex = False; } else { mutex = new CRITICAL_SECTION; myMutex = True; InitializeCriticalSection(mutex); } } S::Threads::MutexWin32::~MutexWin32() { if (myMutex) { DeleteCriticalSection(mutex); delete mutex; } } S::Void *S::Threads::MutexWin32::GetSystemMutex() const { return (Void *) mutex; } S::Bool S::Threads::MutexWin32::Lock() { EnterCriticalSection(mutex); return True; } S::Bool S::Threads::MutexWin32::TryLock() { if (!TryEnterCriticalSection(mutex)) return False; return True; } S::Bool S::Threads::MutexWin32::Release() { LeaveCriticalSection(mutex); return True; } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/win32/semaphorewin32.cpp000077500000000000000000000033161516402577000271430ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Threads::SemaphoreBackend *CreateSemaphoreWin32(S::Int iValue, S::Void *iSemaphore) { return new S::Threads::SemaphoreWin32(iValue, iSemaphore); } S::Int semaphoreWin32Tmp = S::Threads::SemaphoreBackend::SetBackend(&CreateSemaphoreWin32); S::Threads::SemaphoreWin32::SemaphoreWin32(Int iValue, Void *iSemaphore) : SemaphoreBackend(iValue) { type = SEMAPHORE_WIN32; if (iSemaphore != NIL) { semaphore = (HANDLE) iSemaphore; mySemaphore = False; } else { semaphore = CreateSemaphore(NULL, iValue, iValue, NULL); mySemaphore = True; } } S::Threads::SemaphoreWin32::~SemaphoreWin32() { if (mySemaphore && semaphore != NIL) CloseHandle(semaphore); } S::Void *S::Threads::SemaphoreWin32::GetSystemSemaphore() const { return (Void *) semaphore; } S::Bool S::Threads::SemaphoreWin32::Wait() { if (semaphore != NIL && WaitForSingleObject(semaphore, INFINITE) == WAIT_OBJECT_0) return True; return False; } S::Bool S::Threads::SemaphoreWin32::TryWait() { if (semaphore != NIL && WaitForSingleObject(semaphore, 0) == WAIT_OBJECT_0) return True; return False; } S::Bool S::Threads::SemaphoreWin32::Release() { if (semaphore != NIL && ReleaseSemaphore(semaphore, 1, NULL) == 0) return True; return False; } smooth-0.9.11~git20260403.0230c0da/classes/threads/backends/win32/threadwin32.cpp000077500000000000000000000056251516402577000264340ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Threads::ThreadBackend *CreateThreadWin32(S::Void *iThread) { return new S::Threads::ThreadWin32(iThread); } S::Int threadWin32Tmp = S::Threads::ThreadBackend::SetBackend(&CreateThreadWin32); S::Threads::ThreadWin32::ThreadWin32(Void *iThread) { InitializeCriticalSection(&mutex); type = THREAD_WIN32; thread = NIL; threadID = -1; myThread = False; info.threadProc = NIL; info.threadParam = NIL; if (iThread != NIL) thread = (HANDLE) iThread; } S::Threads::ThreadWin32::~ThreadWin32() { if (myThread) Stop(); DeleteCriticalSection(&mutex); } S::Int S::Threads::ThreadWin32::Start(Void (*threadProc)(Void *), Void *threadParam) { Stop(); info.threadProc = threadProc; info.threadParam = threadParam; thread = CreateThread(NULL, 0, Caller, &info, 0, (DWORD *) &threadID); myThread = True; return Success(); } S::Int S::Threads::ThreadWin32::Stop() { EnterCriticalSection(&mutex); if (thread == NIL || threadID == (Int) GetCurrentThreadId()) { LeaveCriticalSection(&mutex); return Error(); } Bool running = IsRunning(); HANDLE thread = this->thread; Bool myThread = this->myThread; this->thread = NIL; LeaveCriticalSection(&mutex); if (running) TerminateThread(thread, 0); if (myThread) CloseHandle(thread); return Success(); } S::Int S::Threads::ThreadWin32::Wait() { EnterCriticalSection(&mutex); if (thread == NIL || threadID == (Int) GetCurrentThreadId()) { LeaveCriticalSection(&mutex); return Error(); } Bool running = IsRunning(); HANDLE thread = this->thread; Bool myThread = this->myThread; this->thread = NIL; LeaveCriticalSection(&mutex); if (running) WaitForSingleObject(thread, INFINITE); if (myThread) CloseHandle(thread); return Success(); } S::Bool S::Threads::ThreadWin32::IsRunning() const { DWORD exitCode = 0; GetExitCodeThread(thread, &exitCode); return (exitCode == STILL_ACTIVE); } S::Void S::Threads::ThreadWin32::Exit() { EnterCriticalSection(&mutex); if (thread == NIL || threadID != (Int) GetCurrentThreadId()) { LeaveCriticalSection(&mutex); return; } HANDLE thread = this->thread; Bool myThread = this->myThread; this->thread = NIL; LeaveCriticalSection(&mutex); if (myThread) CloseHandle(thread); } DWORD WINAPI S::Threads::ThreadWin32::Caller(LPVOID param) { ThreadInfo *info = (ThreadInfo *) param; OleInitialize(NIL); info->threadProc(info->threadParam); OleUninitialize(); return 0; } smooth-0.9.11~git20260403.0230c0da/classes/threads/mutex.cpp000066400000000000000000000025401516402577000227160ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include S::Threads::Mutex::Mutex(Void *iMutex) { backend = MutexBackend::CreateBackendInstance(iMutex); } S::Threads::Mutex::Mutex(const Mutex &oMutex) { *this = oMutex; } S::Threads::Mutex::~Mutex() { delete backend; } S::Threads::Mutex &S::Threads::Mutex::operator =(const Mutex &oMutex) { if (&oMutex == this) return *this; backend = MutexBackend::CreateBackendInstance(NIL); return *this; } S::Int S::Threads::Mutex::GetMutexType() const { return backend->GetMutexType(); } S::Void *S::Threads::Mutex::GetSystemMutex() const { return backend->GetSystemMutex(); } S::Bool S::Threads::Mutex::Lock() { return backend->Lock(); } S::Bool S::Threads::Mutex::TryLock() { return backend->TryLock(); } S::Bool S::Threads::Mutex::Release() { return backend->Release(); } smooth-0.9.11~git20260403.0230c0da/classes/threads/rwlock.cpp000077500000000000000000000044211516402577000230600ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::Threads::RWLock::RWLock() { readLocked = 0; writeLocked = 0; exclusiveAccessMutex = new Mutex(); sharedAccessMutex = new Mutex(); } S::Threads::RWLock::RWLock(const RWLock &oRWLock) { *this = oRWLock; } S::Threads::RWLock::~RWLock() { delete exclusiveAccessMutex; delete sharedAccessMutex; } S::Threads::RWLock &S::Threads::RWLock::operator =(const RWLock &oRWLock) { if (&oRWLock == this) return *this; readLocked = 0; writeLocked = 0; exclusiveAccessMutex = new Mutex(); sharedAccessMutex = new Mutex(); return *this; } S::Bool S::Threads::RWLock::LockForRead() { /* Acquire exclusive lock. */ exclusiveAccessMutex->Lock(); /* Increase read lock counter by one. */ sharedAccessMutex->Lock(); readLocked++; sharedAccessMutex->Release(); /* Allow other read and write locks. */ exclusiveAccessMutex->Release(); return True; } S::Bool S::Threads::RWLock::LockForWrite() { /* Acquire exclusive lock. */ exclusiveAccessMutex->Lock(); /* Wait for read operations to finish. */ sharedAccessMutex->Lock(); while (readLocked) { sharedAccessMutex->Release(); exclusiveAccessMutex->Release(); S::System::System::Sleep(0); exclusiveAccessMutex->Lock(); sharedAccessMutex->Lock(); } /* Increase write lock counter. */ writeLocked++; sharedAccessMutex->Release(); return True; } S::Bool S::Threads::RWLock::Release() { /* Check if we are locked for write. */ sharedAccessMutex->Lock(); if (writeLocked && !readLocked) { /* Decrease write lock counter. */ writeLocked--; sharedAccessMutex->Release(); /* Allow new read and write locks again. */ exclusiveAccessMutex->Release(); return True; } /* Decrease read lock counter by one. */ readLocked--; sharedAccessMutex->Release(); return True; } smooth-0.9.11~git20260403.0230c0da/classes/threads/semaphore.cpp000066400000000000000000000027351516402577000235450ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2016 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::Threads::Semaphore::Semaphore(Int iValue, Void *iSemaphore) { backend = SemaphoreBackend::CreateBackendInstance(iValue, iSemaphore); max = iValue; } S::Threads::Semaphore::Semaphore(const Semaphore &oSemaphore) { *this = oSemaphore; } S::Threads::Semaphore::~Semaphore() { delete backend; } S::Threads::Semaphore &S::Threads::Semaphore::operator =(const Semaphore &oSemaphore) { if (&oSemaphore == this) return *this; backend = SemaphoreBackend::CreateBackendInstance(oSemaphore.max, NIL); max = oSemaphore.max; return *this; } S::Int S::Threads::Semaphore::GetSemaphoreType() const { return backend->GetSemaphoreType(); } S::Void *S::Threads::Semaphore::GetSystemSemaphore() const { return backend->GetSystemSemaphore(); } S::Bool S::Threads::Semaphore::Wait() { return backend->Wait(); } S::Bool S::Threads::Semaphore::TryWait() { return backend->TryWait(); } S::Bool S::Threads::Semaphore::Release() { return backend->Release(); } smooth-0.9.11~git20260403.0230c0da/classes/threads/thread.cpp000066400000000000000000000056151516402577000230310ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2021 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include namespace smooth { static multithread (intptr_t) threadID = Threads::MainThreadID; } const S::Short S::Threads::Thread::classID = S::Object::RequestClassID(); S::Short S::Threads::Thread::nOfRunningThreads = 0; S::Threads::Thread::Thread(Void *iThread) { backend = ThreadBackend::CreateBackendInstance(iThread); type = classID; status = THREAD_CREATED; } S::Threads::Thread::Thread(const Thread &oThread) { *this = oThread; } S::Threads::Thread::~Thread() { if (status == THREAD_CREATED || status == THREAD_STARTME) { status = THREAD_STOPPED; } if (status != THREAD_STOPPED) { status = THREAD_STOPPED; Access::Decrement(nOfRunningThreads); backend->Stop(); } delete backend; } S::Threads::Thread &S::Threads::Thread::operator =(const Thread &oThread) { if (&oThread == this) return *this; backend = ThreadBackend::CreateBackendInstance(NIL); type = classID; status = THREAD_CREATED; threadMain = oThread.threadMain; return *this; } S::Short S::Threads::Thread::GetStatus() const { return status; } S::UnsignedInt32 S::Threads::Thread::GetThreadID() const { return GetHandle(); } S::UnsignedInt32 S::Threads::Thread::GetCurrentThreadID() { return threadID; } S::Bool S::Threads::Thread::IsCurrentThread() const { if (GetCurrentThreadID() == GetThreadID()) return True; return False; } S::Int S::Threads::Thread::Start() { if ((status == THREAD_CREATED || status == THREAD_STARTME) && !initializing) { Access::Increment(nOfRunningThreads); status = THREAD_RUNNING; backend->Start((Void (*)(Void *)) MainCaller, this); return Success(); } else if (status == THREAD_CREATED && initializing) { status = THREAD_STARTME; return Success(); } return Error(); } S::Int S::Threads::Thread::Stop() { if (backend->Stop() == Success()) { status = THREAD_STOPPED; Access::Decrement(nOfRunningThreads); return Success(); } return Error(); } S::Int S::Threads::Thread::Wait() { return backend->Wait(); } S::Void S::Threads::Thread::MainCaller(Thread *thread) { /* Set thread ID and call thread callback. */ threadID = thread->GetHandle(); thread->threadMain.Call(thread); /* Clean up and exit thread. */ String::DeleteTemporaryBuffers(True); thread->status = THREAD_STOPPED; Access::Decrement(nOfRunningThreads); thread->backend->Exit(); } smooth-0.9.11~git20260403.0230c0da/classes/xml/000077500000000000000000000000001516402577000202155ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/xml/Makefile000066400000000000000000000020151516402577000216530ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../.. include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options # Change these variables to fit your project: ifeq ($(USE_BUNDLED_LIBXML2),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support/libxml2 -DLIBXML_STATIC else ifeq ($(BUILD_OSX),True) MYCCOPTS += -I$(shell xcodebuild -sdk macosx -version | grep "^Path: " | head -n 1 | tail -c +7)/usr/include/libxml2 else MYCCOPTS += $(shell pkg-config --cflags libxml-2.0) endif ifeq ($(USE_BUNDLED_LIBICONV),True) MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support/libiconv else MYCCOPTS += -I/usr/local/include endif # Enter object files here: OBJECTS = attribute.o document.o node.o # Enter addition commands for targets all and clean here: ALLCMD1 = $(call makein,xul) CLEANCMD1 = $(call cleanin,xul) ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/xml/attribute.cpp000066400000000000000000000030011516402577000227160ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include S::Array S::XML::Attribute::attributeNames; S::XML::Attribute::Attribute(const String &iName, const String &iContent) { attributeID = -1; nameIndex = iName.ComputeCRC32(); content = iContent; if (attributeNames.Get(nameIndex) == NIL) attributeNames.Add(iName, nameIndex); } S::XML::Attribute::~Attribute() { } S::Int S::XML::Attribute::GetAttributeID() const { return attributeID; } S::Int S::XML::Attribute::SetAttributeID(Int newID) { attributeID = newID; return Success(); } const S::String &S::XML::Attribute::GetName() const { return attributeNames.Get(nameIndex); } S::Int S::XML::Attribute::SetName(const String &newName) { nameIndex = newName.ComputeCRC32(); if (attributeNames.Get(nameIndex) == NIL) attributeNames.Add(newName, nameIndex); return Success(); } const S::String &S::XML::Attribute::GetContent() const { return content; } S::Int S::XML::Attribute::SetContent(const String &newContent) { content = newContent; return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/xml/document.cpp000066400000000000000000000105671516402577000225500ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2020 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include S::XML::Document::Document() { rootNode = NIL; ownRoot = False; encoding = "UTF-8"; } S::XML::Document::Document(const Document &oDocument) { rootNode = new Node(*oDocument.GetRootNode()); ownRoot = True; encoding = oDocument.encoding; } S::XML::Document::~Document() { if (rootNode != NIL && ownRoot) delete rootNode; } S::XML::Node *S::XML::Document::GetRootNode() const { return rootNode; } S::Int S::XML::Document::SetRootNode(Node *newRootNode) { rootNode = newRootNode; ownRoot = False; return Success(); } S::Int S::XML::Document::SetEncoding(const String &newEncoding) { encoding = newEncoding; return Success(); } S::Int S::XML::Document::LoadFile(const String &fileName) { if (!File(fileName).Exists()) return Error(); xmlTextReaderPtr reader = xmlNewTextReaderFilename(fileName.ConvertTo("UTF-8")); if (reader == NIL) return Error(); Int ret = 1; while ((ret = xmlTextReaderRead(reader)) == 1) { if (xmlTextReaderNodeType(reader) == XML_ELEMENT_NODE) { String::InputFormat inputFormat("UTF-8"); rootNode = new Node(NIL); ownRoot = True; LoadNode(reader, rootNode); break; } } xmlFreeTextReader(reader); if (ret >= 0) return Success(); else return Error(); } S::Int S::XML::Document::ParseMemory(const Void *memory, Int size) { xmlParserInputBufferPtr buffer = xmlParserInputBufferCreateMem((char *) memory, size, XML_CHAR_ENCODING_NONE); if (buffer == NIL) { return Error(); } xmlTextReaderPtr reader = xmlNewTextReader(buffer, NIL); if (reader == NIL) { xmlFreeParserInputBuffer(buffer); return Error(); } Int ret = 1; while ((ret = xmlTextReaderRead(reader)) == 1) { if (xmlTextReaderNodeType(reader) == XML_ELEMENT_NODE) { String::InputFormat inputFormat("UTF-8"); rootNode = new Node(NIL); ownRoot = True; LoadNode(reader, rootNode); break; } } xmlFreeTextReader(reader); xmlFreeParserInputBuffer(buffer); if (ret >= 0) return Success(); else return Error(); } S::Int S::XML::Document::LoadNode(xmlTextReaderPtr reader, Node *node) { node->SetName((const char *) xmlTextReaderConstName(reader)); if (xmlTextReaderHasAttributes(reader)) { while (xmlTextReaderMoveToNextAttribute(reader) == 1) node->SetAttribute((const char *) xmlTextReaderConstName(reader), (const char *) xmlTextReaderConstValue(reader)); xmlTextReaderMoveToElement(reader); } if (!xmlTextReaderIsEmptyElement(reader)) { Int nodeType = 0; if (xmlTextReaderRead(reader) == -1) return Error(); while ((nodeType = xmlTextReaderNodeType(reader)) != XML_ELEMENT_DECL) { if (nodeType == XML_ELEMENT_NODE) LoadNode(reader, node->AddNode(NIL)); else if (nodeType == XML_TEXT_NODE || nodeType == XML_CDATA_SECTION_NODE) node->SetContent((const char *) xmlTextReaderConstValue(reader)); if (xmlTextReaderRead(reader) == -1) return Error(); } } return Success(); } S::Int S::XML::Document::SaveFile(const String &fileName) { xmlTextWriterPtr writer = xmlNewTextWriterFilename(fileName.ConvertTo("UTF-8"), 0); xmlTextWriterSetIndent(writer, 1); xmlTextWriterStartDocument(writer, "1.0", encoding, NIL); if (rootNode != NIL) SaveNode(writer, rootNode); xmlTextWriterEndDocument(writer); xmlFreeTextWriter(writer); return Success(); } S::Int S::XML::Document::SaveNode(xmlTextWriterPtr writer, Node *node) { xmlTextWriterStartElement(writer, (xmlChar *) node->GetName().ConvertTo("UTF-8")); for (Int i = 0; i < node->GetNOfAttributes(); i++) xmlTextWriterWriteAttribute(writer, (xmlChar *) node->GetNthAttribute(i)->GetName().ConvertTo("UTF-8"), (xmlChar *) node->GetNthAttribute(i)->GetContent().ConvertTo("UTF-8")); xmlTextWriterWriteString(writer, (xmlChar *) node->GetContent().ConvertTo("UTF-8")); for (Int i = 0; i < node->GetNOfNodes(); i++) SaveNode(writer, node->GetNthNode(i)); xmlTextWriterEndElement(writer); return Success(); } smooth-0.9.11~git20260403.0230c0da/classes/xml/node.cpp000066400000000000000000000116331516402577000216520ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2022 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include S::Array S::XML::Node::elementNames; S::XML::Node::Node(const String &iName, const String &iContent) { nodeID = -1; nameIndex = iName.ComputeCRC32(); content = iContent; attributes = NIL; subnodes = NIL; if (elementNames.Get(nameIndex) == NIL) elementNames.Add(iName, nameIndex); } S::XML::Node::Node(const Node &oNode) { nodeID = -1; nameIndex = oNode.nameIndex; content = oNode.content; attributes = NIL; subnodes = NIL; /* Copy attributes. */ if (oNode.attributes != NIL) { foreach (Attribute *oAttribute, *oNode.attributes) { Attribute *attribute = new Attribute(*oAttribute); if (attributes == NIL) attributes = new Array(); attribute->SetAttributeID(attributes->Add(attribute)); } } /* Copy subnodes. */ if (oNode.subnodes != NIL) { foreach (Node *oSubnode, *oNode.subnodes) { Node *node = new Node(*oSubnode); if (subnodes == NIL) subnodes = new Array(); node->SetNodeID(subnodes->Add(node)); } } } S::XML::Node::~Node() { /* Delete attributes. */ if (attributes != NIL) { foreach (Attribute *attribute, *attributes) delete attribute; delete attributes; } /* Delete subnodes. */ if (subnodes != NIL) { foreach (Node *subnode, *subnodes) delete subnode; delete subnodes; } } S::Int S::XML::Node::GetNodeID() const { return nodeID; } S::Int S::XML::Node::SetNodeID(Int newID) { nodeID = newID; return Success(); } const S::String &S::XML::Node::GetName() const { return elementNames.Get(nameIndex); } S::Int S::XML::Node::SetName(const String &newName) { nameIndex = newName.ComputeCRC32(); if (elementNames.Get(nameIndex) == NIL) elementNames.Add(newName, nameIndex); return Success(); } const S::String &S::XML::Node::GetContent() const { return content; } S::Int S::XML::Node::SetContent(const String &newContent) { content = newContent; return Success(); } S::Int S::XML::Node::GetNOfAttributes() const { if (attributes == NIL) return 0; return attributes->Length(); } S::XML::Attribute *S::XML::Node::GetNthAttribute(Int attributeNumber) const { if (attributeNumber >= GetNOfAttributes()) return NIL; return attributes->GetNth(attributeNumber); } S::XML::Attribute *S::XML::Node::GetAttributeByName(const String &attributeName) const { Int nOfAttributes = GetNOfAttributes(); if (nOfAttributes == 0) return NIL; Int nameIndex = attributeName.ComputeCRC32(); for (Int i = 0; i < nOfAttributes; i++) { Attribute *attribute = GetNthAttribute(i); if (attribute->nameIndex == nameIndex) return attribute; } return NIL; } S::XML::Attribute *S::XML::Node::SetAttribute(const String &attributeName, const String &attributeContent) { Attribute *attribute = GetAttributeByName(attributeName); if (attribute == NIL) { attribute = new Attribute(attributeName, attributeContent); if (attributes == NIL) attributes = new Array(); attribute->SetAttributeID(attributes->Add(attribute)); } else { attribute->SetContent(attributeContent); } return attribute; } S::Int S::XML::Node::RemoveAttribute(Attribute *attribute) { if (attribute == NIL) return Error(); attributes->Remove(attribute->GetAttributeID()); delete attribute; return Success(); } S::Int S::XML::Node::RemoveAttributeByName(const String &attributeName) { return RemoveAttribute(GetAttributeByName(attributeName)); } S::Int S::XML::Node::GetNOfNodes() const { if (subnodes == NIL) return 0; return subnodes->Length(); } S::XML::Node *S::XML::Node::GetNthNode(Int nodeNumber) const { if (nodeNumber >= GetNOfNodes()) return NIL; return subnodes->GetNth(nodeNumber); } S::XML::Node *S::XML::Node::GetNodeByName(const String &nodeName) const { Int nOfNodes = GetNOfNodes(); if (nOfNodes == 0) return NIL; Int nameIndex = nodeName.ComputeCRC32(); for (Int i = 0; i < nOfNodes; i++) { Node *node = GetNthNode(i); if (node->nameIndex == nameIndex) return node; } return NIL; } S::XML::Node *S::XML::Node::AddNode(const String &iName, const String &iContent) { Node *node = new Node(iName, iContent); if (subnodes == NIL) subnodes = new Array(); node->SetNodeID(subnodes->Add(node)); return node; } S::Int S::XML::Node::RemoveNode(Node *node) { if (node == NIL) return Error(); subnodes->Remove(node->GetNodeID()); delete node; return Success(); } S::Int S::XML::Node::RemoveNodeByName(const String &nodeName) { return RemoveNode(GetNodeByName(nodeName)); } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/000077500000000000000000000000001516402577000210255ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/Makefile000066400000000000000000000005771516402577000224760ustar00rootroot00000000000000########## smooth directory makefile ########## # Change these variables to fit this location: SMOOTH_PATH = ../../.. # Enter object files here: OBJECTS = box.o button.o description.o label.o menubar.o popupmenu.o renderer.o textbox.o widget.o window.o ## Do not change anything below this line. ## include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/box.cpp000077500000000000000000000064411516402577000223310ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include S::XML::XUL::Box::Box(Node *node) : Widget(node) { layer = NIL; if (node != NIL) { layer = new GUI::Layer(); if (node->GetName() == "hbox") orient = HORIZONTAL; else if (node->GetName() == "vbox") orient = VERTICAL; for (Int i = 0; i < node->GetNOfNodes(); i++) { Node *nNode = node->GetNthNode(i); XUL::Widget *widget = NIL; if (nNode->GetName() == "box" || nNode->GetName() == "hbox" || nNode->GetName() == "vbox") { widget = new XUL::Box(nNode); layer->Add(widget->GetWidget()); widgets.Add(widget); } else if (nNode->GetName() == "button") { widget = new XUL::Button(nNode); layer->Add(widget->GetWidget()); widgets.Add(widget); } else if (nNode->GetName() == "textbox") { widget = new XUL::TextBox(nNode); layer->Add(widget->GetWidget()); widgets.Add(widget); } else if (nNode->GetName() == "label") { widget = new XUL::Label(nNode); layer->Add(widget->GetWidget()); widgets.Add(widget); } else if (nNode->GetName() == "description") { widget = new XUL::Description(nNode); layer->Add(widget->GetWidget()); widgets.Add(widget); } } CalculateChildMetrics(); } } S::XML::XUL::Box::~Box() { for (Int i = 0; i < widgets.Length(); i++) delete widgets.GetNth(i); widgets.RemoveAll(); if (layer != NIL) Object::DeleteObject(layer); } S::GUI::Widget *S::XML::XUL::Box::GetWidget() const { return layer; } S::Void S::XML::XUL::Box::CalculateChildMetrics() { if (widgets.Length() == 0) return; Int xOffset = 0; Int yOffset = 0; Int maxWidth = 0; Int maxHeight = 0; Int elementWidth = width / widgets.Length(); Int elementHeight = height / widgets.Length(); for (Int i = 0; i < widgets.Length(); i++) { XUL::Widget *widget = widgets.GetNth(i); maxWidth = Math::Max(maxWidth, widget->GetWidth()); maxHeight = Math::Max(maxHeight, widget->GetHeight()); Int usedElementWidth = widget->GetWidth(); Int usedElementHeight = widget->GetHeight(); if (usedElementWidth == 0) usedElementWidth = (orient == HORIZONTAL) ? elementWidth : widget->GetDefaultWidth(); if (usedElementHeight == 0) usedElementHeight = (orient == VERTICAL) ? elementHeight : widget->GetDefaultHeight(); widget->SetMetrics(GUI::Point(xOffset, yOffset), GUI::Size(usedElementWidth, usedElementHeight)); if (orient == HORIZONTAL) xOffset += usedElementWidth; else if (orient == VERTICAL) yOffset += usedElementHeight; } } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/button.cpp000077500000000000000000000020641516402577000230510ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2019 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::XML::XUL::Button::Button(Node *node) : Widget(node) { button = NIL; defaultWidth = 80; defaultHeight = 22; if (node != NIL) { button = new GUI::Button(GetXMLAttributeValue(node, "label"), GUI::Point(0, 0), GUI::Size(0, 0)); if (GetXMLAttributeValue(node, "disabled") == "true") button->Deactivate(); } } S::XML::XUL::Button::~Button() { if (button != NIL) Object::DeleteObject(button); } S::GUI::Widget *S::XML::XUL::Button::GetWidget() const { return button; } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/description.cpp000077500000000000000000000016441516402577000240640ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::XML::XUL::Description::Description(Node *node) : Widget(node) { text = NIL; if (node != NIL) { text = new GUI::Text(node->GetContent(), GUI::Point(0, 0)); } } S::XML::XUL::Description::~Description() { if (text != NIL) Object::DeleteObject(text); } S::GUI::Widget *S::XML::XUL::Description::GetWidget() const { return text; } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/label.cpp000077500000000000000000000016211516402577000226130ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::XML::XUL::Label::Label(Node *node) : Widget(node) { text = NIL; if (node != NIL) { text = new GUI::Text(GetXMLAttributeValue(node, "value"), GUI::Point(0, 0)); } } S::XML::XUL::Label::~Label() { if (text != NIL) Object::DeleteObject(text); } S::GUI::Widget *S::XML::XUL::Label::GetWidget() const { return text; } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/menubar.cpp000066400000000000000000000027041516402577000231650ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include S::XML::XUL::Menubar::Menubar(Node *node) : Widget(node) { menubar = NIL; if (node != NIL) { menubar = new GUI::Menubar(); for (Int i = 0; i < node->GetNOfNodes(); i++) { Node *mNode = node->GetNthNode(i); if (mNode->GetName() == "menu") { XUL::PopupMenu *menu = new XUL::PopupMenu(mNode); menubar->AddEntry(menu->GetName(), NIL, (GUI::PopupMenu *) menu->GetWidget()); entries.Add(menu); } else if (mNode->GetName() == "toolbarbutton") { menubar->AddEntry(GetXMLAttributeValue(mNode, "label")); } } } } S::XML::XUL::Menubar::~Menubar() { for (Int i = 0; i < entries.Length(); i++) delete entries.GetNth(i); entries.RemoveAll(); if (menubar != NIL) Object::DeleteObject(menubar); } S::GUI::Widget *S::XML::XUL::Menubar::GetWidget() const { return menubar; } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/popupmenu.cpp000066400000000000000000000033241516402577000235630ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::XML::XUL::PopupMenu::PopupMenu(Node *node) : Widget(node) { menu = NIL; if (node != NIL) { name = GetXMLAttributeValue(node, "label"); if (node->GetNthNode(0)->GetName() == "menupopup") { node = node->GetNthNode(0); menu = new GUI::PopupMenu(); for (Int i = 0; i < node->GetNOfNodes(); i++) { Node *entry = node->GetNthNode(i); if (entry->GetName() == "menuitem") { menu->AddEntry(GetXMLAttributeValue(entry, "label")); } else if (entry->GetName() == "menuseparator") { menu->AddEntry(); } else if (entry->GetName() == "menu") { XUL::PopupMenu *popup = new XUL::PopupMenu(entry); menu->AddEntry(popup->GetName(), NIL, (GUI::PopupMenu *) popup->GetWidget()); entries.Add(popup); } } } } } S::XML::XUL::PopupMenu::~PopupMenu() { for (Int i = 0; i < entries.Length(); i++) delete entries.GetNth(i); entries.RemoveAll(); if (menu != NIL) delete menu; } const S::String &S::XML::XUL::PopupMenu::GetName() const { return name; } S::GUI::Widget *S::XML::XUL::PopupMenu::GetWidget() const { return menu; } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/renderer.cpp000066400000000000000000000026261516402577000233450ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include S::XML::XUL::Renderer::Renderer() : Widget(NIL) { window = NIL; } S::XML::XUL::Renderer::~Renderer() { CloseXUL(); } S::Int S::XML::XUL::Renderer::LoadXUL(const String &fileName) { CloseXUL(); Int rVal = Error(); Document *xul = new Document(); xul->LoadFile(fileName); if (xul->GetRootNode() != NIL) rVal = RenderXUL(xul); delete xul; return rVal; } S::Int S::XML::XUL::Renderer::CloseXUL() { if (window != NIL) delete window; window = NIL; return Success(); } S::GUI::Widget *S::XML::XUL::Renderer::GetWidget() const { if (window == NIL) return NIL; return window->GetWidget(); } S::Int S::XML::XUL::Renderer::RenderXUL(Document *xul) { if (xul->GetRootNode()->GetName() == "window") { window = new XUL::Window(xul->GetRootNode()); return Success(); } return Error(); } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/textbox.cpp000077500000000000000000000027101516402577000232310ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include S::XML::XUL::TextBox::TextBox(Node *node) : Widget(node) { editBox = NIL; if (node != NIL) { if (GetXMLAttributeValue(node, "multiline") == "true") editBox = new GUI::MultiEdit(GetXMLAttributeValue(node, "value"), GUI::Point(0, 0), GUI::Size(0, 0), GetXMLAttributeValue(node, "maxlength").ToInt()); else editBox = new GUI::EditBox(GetXMLAttributeValue(node, "value"), GUI::Point(0, 0), GUI::Size(0, 0), GetXMLAttributeValue(node, "maxlength").ToInt()); if (GetXMLAttributeValue(node, "disabled") == "true") editBox->Deactivate(); if (GetXMLAttributeValue(node, "type") == "password") editBox->SetFlags(editBox->GetFlags() | GUI::EDB_ASTERISK); } } S::XML::XUL::TextBox::~TextBox() { if (editBox != NIL) Object::DeleteObject(editBox); } S::GUI::Widget *S::XML::XUL::TextBox::GetWidget() const { return editBox; } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/widget.cpp000066400000000000000000000043511516402577000230170ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2013 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include const S::Short S::XML::XUL::Widget::HORIZONTAL = 0; const S::Short S::XML::XUL::Widget::VERTICAL = 1; S::XML::XUL::Widget::Widget(Node *node) { defaultWidth = 100; defaultHeight = 20; if (node != NIL) { id = GetXMLAttributeValue(node, "id"); orient = (GetXMLAttributeValue(node, "orient") == "vertical") ? VERTICAL : HORIZONTAL; left = GetXMLAttributeValue(node, "left").ToInt(); top = GetXMLAttributeValue(node, "top").ToInt(); width = GetXMLAttributeValue(node, "width").ToInt(); height = GetXMLAttributeValue(node, "height").ToInt(); minwidth = GetXMLAttributeValue(node, "minwidth").ToInt(); minheight = GetXMLAttributeValue(node, "minheight").ToInt(); maxwidth = GetXMLAttributeValue(node, "maxwidth").ToInt(); maxheight = GetXMLAttributeValue(node, "maxheight").ToInt(); flex = GetXMLAttributeValue(node, "flex").ToInt(); statustext = GetXMLAttributeValue(node, "statustext"); tooltiptext = GetXMLAttributeValue(node, "tooltiptext"); } else { orient = HORIZONTAL; left = 0; top = 0; width = 0; height = 0; minwidth = 0; minheight = 0; maxwidth = 0; maxheight = 0; flex = 0; } } S::XML::XUL::Widget::~Widget() { } S::GUI::Widget *S::XML::XUL::Widget::GetWidget() const { return NIL; } S::Int S::XML::XUL::Widget::SetMetrics(const GUI::Point &pos, const GUI::Size &size) { return GetWidget()->SetMetrics(pos, size); } S::String S::XML::XUL::Widget::GetXMLAttributeValue(Node *node, const String &attribute) const { if (node != NIL) { if (node->GetAttributeByName(attribute) != NIL) { return node->GetAttributeByName(attribute)->GetContent(); } } return NIL; } smooth-0.9.11~git20260403.0230c0da/classes/xml/xul/window.cpp000066400000000000000000000043221516402577000230410ustar00rootroot00000000000000 /* The smooth Class Library * Copyright (C) 1998-2009 Robert Kausch * * This library is free software; you can redistribute it and/or * modify it under the terms of "The Artistic License, Version 2.0". * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include S::XML::XUL::Window::Window(Node *node) : Widget(node) { titlebar = NIL; window = NIL; if (node != NIL) { window = new GUI::Window(GetXMLAttributeValue(node, "title"), GUI::Point(GetXMLAttributeValue(node, "screenX").ToInt(), GetXMLAttributeValue(node, "screenY").ToInt()), GUI::Size(width, height)); if (GetXMLAttributeValue(node, "hidechrome") != "true" && GetXMLAttributeValue(node, "hidechrome") != "1") { titlebar = new GUI::Titlebar(); window->Add(titlebar); } if (GetXMLAttributeValue(node, "sizemode") == "maximized") window->Maximize(); if (GetXMLAttributeValue(node, "sizemode") == "minimized") window->Minimize(); for (Int i = 0; i < node->GetNOfNodes(); i++) { Node *nNode = node->GetNthNode(i); if (nNode->GetName() == "toolbox") { for (Int j = 0; j < nNode->GetNOfNodes(); j++) { Node *tNode = nNode->GetNthNode(j); if (tNode->GetName() == "menubar" || tNode->GetName() == "toolbar") { XUL::Menubar *menu = new XUL::Menubar(tNode); window->Add(menu->GetWidget()); widgets.Add(menu); } } } } XUL::Box *box = new XUL::Box(node); window->Add(box->GetWidget()); widgets.Add(box); } } S::XML::XUL::Window::~Window() { for (Int i = 0; i < widgets.Length(); i++) delete widgets.GetNth(i); widgets.RemoveAll(); if (titlebar != NIL) Object::DeleteObject(titlebar); if (window != NIL) Object::DeleteObject(window); } S::GUI::Widget *S::XML::XUL::Window::GetWidget() const { return window; } smooth-0.9.11~git20260403.0230c0da/configure000077500000000000000000000022111516402577000176630ustar00rootroot00000000000000#!/bin/sh echo "There is no need to run configure for building smooth. Just make sure" echo "the following prerequisites are met before running make:" echo echo " On Linux, *BSD, Solaris, Hurd:" echo echo " - libbz2 / libbzip2 development package" echo " - libcurl development package" echo " - libfribidi development package" echo " - libgtk+3.0 development package" echo " - libjpeg development package" echo " - libxml2 development package" echo echo " - smooth uses a bundled version of libcpuid by default. To use" echo " the library installed on your system, please build with" echo " \"make config=systemlibcpuid\"." echo echo " On macOS:" echo echo " - Building smooth is supported on macOS 10.5.8 Leopard and later" echo " using the Xcode Command Line Tools (no Xcode project file provided)" echo echo " On Windows:" echo echo " - Please use MSYS2 (https://www.msys2.org/) or Visual Studio 2022" echo " with the msvc/smooth.sln project file to build smooth" echo echo "When all prerequisites are met, simply run \"make && make install\"." echo smooth-0.9.11~git20260403.0230c0da/doc/000077500000000000000000000000001516402577000165255ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/doc/Backends000066400000000000000000000004711516402577000201640ustar00rootroot00000000000000Implemented smooth system backends ---------------------------------- X = implemented P = partially implemented U = unnecessary n.a. = not applicable Generic Threads Timers Events Windows Bitmaps Surfaces Win32 X X X X X X X Xlib X n.a. - - P - - SDL X X X - n.a. - - POSIX U X - - n.a. n.a. n.a. smooth-0.9.11~git20260403.0230c0da/doc/BugList000066400000000000000000000117721516402577000200310ustar00rootroot00000000000000smooth bug list --------------- Unfixed bugs: no known unfixed bugs ------------------------------------------------------------------------ 07.01.03 - smooth alpha 0.8.61.0 #0019 - Fehler bei Popups die Statusbar-Infos enthalten Repro: Programm starten und aus einem entspr. Popup ein Submenü aufrufen Sym: Grafikfehler Rea: Fehler beim Eintragen der Statusbar-Infos Stat: fixed Occ: 08.04.03 12.01.02 - smooth alpha 0.8.58.0 #0018 - Instabile Popupmenüs Repro: Programm starten und Menüeinträge in Popups anklicken Sym: Programm stürzt ab Rea: Ursache liegt in der Art, wie Popupmenüs gelöscht werden. Nach dem Löschen ist noch eine Funktion (Process(...) mit SM_LBUTTONUP) des Popups aktiv. Stat: fixed Occ: 15.02.02 06.06.01 - smooth alpha 0.8.54.0 #0017 - ComboBoxen öffnen sich nicht Repro: Programm starten, ComboBox anklicken Sym: ComboBox öffnet sich nicht, bzw wird sofort wieder geschlossen Rea: smooth::GetObject sieht ToolWindows nicht als Typ OBJ_WINDOW an Stat: fixed Occ: 07.06.01 30.03.01 - smooth alpha 0.8.50.0 #0016 - Serverauswahl hängt Repro: Session auswählen, Server beenden, erneut verbinden Sym: Dialog bleibt hängen Rea: ? Stat: fixed Occ: 30.03.01 22.03.01 - smooth alpha 0.8.50.0 #0015 - Serverauswahl stürzt ab Repro: Session auswählen und dann den Server beenden Sym: Programm stürzt ab Rea: Dialog merkt nicht, dass der Server beendet wurde Stat: fixed Occ: 30.03.01 22.03.01 - smooth alpha 0.8.50.0 #0014 - Serverauswahl hängt Repro: Geschützte Session auswählen und als Passwort fidsa eingeben Sym: Dialog bleibt hängen Rea: durch XOR werden Zeichen des Passworts 0 Stat: fixed Occ: 27.06.01 01.02.01 - smooth alpha 0.8.41.1 #0013 - Programm startet nicht richtig Repro: Test starten (tritt nur gelegentlich auf) Sym: Widgets werden nicht gezeichnet Rea: RecArray Kette wurde während eines Durchlaufs verändert Stat: fixed Occ: 22.07.01 13.09.00 - smooth alpha 0.8.7.1 #0012 - Programm wird nicht beendet, wenn ein Thread aktiv ist Repro: Test starten und beenden, ohne den MBThread zu beenden Sym: Test bleibt im Speicher Rea: Threads werden nicht zerstört bzw. beendet Stat: fixed Occ: 21.09.00 04.08.00 - smooth alpha 0.7.26.1 #0011 - ListBox aktiviert mehrere Einträge Repro: ListBox mit vielen Einträgen erzeugen Eintrag auswählen Sym: Manchmal sind mehrere Einträge selektiert Rea: Fehler in ListBox Stat: fixed Occ: 05.08.00 06.07.00 - smooth alpha 0.7.21.1 #0010 - nur letzte ComboBox funktioniert Repro: mehrere ComboBoxen erstellen, Eintrag aus erster anwählen Sym: Programm stürzt sofort ab Rea: listbox wurde nicht auf NULL überprüft Stat: fixed Occ: 12.07.00 06.07.00 - smooth alpha 0.7.21.1 #0009 - ComboBox zeichnet Hintergrund nicht neu Repro: ComboBox öffnen und schließen Sym: Bereich hinter der ComboBox wird nicht gezeichnet Rea: nicht implementiert Stat: fixed Occ: 07.07.00 04.06.00 - smooth alpha 0.7.14.0 #0008 - Läuft nicht unter Windows 2000 Final Repro: Anwendung unter Windows 2000 starten Sym: Hauptfenster wird nicht geöffnet Rea: hCursor Feld von WNDCLASSEX nicht gesetzt Stat: fixed Occ: 06.06.00 28.05.00 - smooth alpha 0.7.11.0 #0007 - Zeichnet in falschen DC Repro: Fenster maximieren andere maximierte Anwendung aktivieren smooth Fenster aktivieren Tritt nur auf, wenn Process() auf WM_GETMINMAXINFO o.ä. reagiert Sym: Fenster wird nicht neugezeichnet Rea: ? Stat: fixed Occ: 28.05.00 14.04.00 - smooth alpha 0.6.26.0 #0006 - Fehlerhafte Darstellung bei großen Schriftarten Repro: smooth Anwendung bei großen Schriftarten starten Sym: Text wird zu groß gezeichnet Rea: Fehlerhafte Texthöhenberechnung Stat: fixed Occ: 14.04.00 13.04.00 - smooth alpha 0.6.25.1 #0005 - Objekte Zeichnen manchmal in DeviceContext des Desktop Repro: Dialogfenster mit Layer öffnen funktioniert nur unter Windows 9x Sym: Objekte werden außerhalb eines Fensters gezeichnet Rea: Fehler in window.cpp und layer.cpp Stat: fixed Occ: 14.04.00 02.04.00 - smooth alpha 0.6.22.0 #0004 - Absturz bei MultiButton MessageBoxen Repro: MessageBox öffnen auf Abbrechen klicken Sym: sofortiger Absturz Rea: Buttons werden in messagebox.cpp nicht richtig unregistriert Stat: fixed Occ: 02.04.00 22.03.00 - smooth alpha 0.6.20.0 #0003 - Fehler bei ComboBoxen Repro: ComboBox öffnen Slider einer anderen ListBox bewegen Sym: ComboBox wird nicht geschlossen Rea: ? Stat: fixed Occ: 07.06.00 19.03.00 - smooth alpha 0.6.18.0 #0002 - Abstürze bei ListBoxen Repro: test.exe starten Scrollbar der ListBox mehrmals bewegen Sym: sofortiger Absturz Rea: Falsche Behandlung von Doppelklicks in scrollbar.cpp Stat: fixed Occ: 14.04.00 17.03.00 - smooth alpha 0.6.16.1 #0001 - Programm stürzt gelegentlich ab Repro: ? Sym: Absturz nach Beenden des Programms Rea: eventuell fehlerhafte deregistrierung von Objekten in Programm Stat: fixed Occ: 17.03.00 smooth-0.9.11~git20260403.0230c0da/doc/Compatibility000066400000000000000000000012041516402577000212560ustar00rootroot00000000000000General requirements -------------------- smooth can be compiled using GCC 4.0+ or Microsoft Visual C++ 2015. Supported operating systems --------------------------- Windows Vista/7/8/10 complete support Windows 2000/XP complete support macOS 10.5+ complete support Linux complete support Solaris 11.x complete support FreeBSD 9.0+ complete support NetBSD 6.0+ complete support OpenBSD 5.1+ complete support GNU Hurd complete support Haiku OS complete support Discontinued operating systems ------------------------------ Windows NT 4.0 no longer supported Windows 9x/ME no longer supported QNX 6.5 no longer supported smooth-0.9.11~git20260403.0230c0da/doc/Rules000066400000000000000000000004551516402577000175460ustar00rootroot00000000000000- classes that derive from a smooth::Object and have their own classID need to implement IsTypeCompatile - classes that implement IsTypeCompatible must care for being removed from containers on destruction - always use Object::DeleteObject to delete smooth objects, otherwise the program might crash smooth-0.9.11~git20260403.0230c0da/doc/changelog/000077500000000000000000000000001516402577000204545ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.1999000066400000000000000000000136611516402577000226470ustar00rootroot00000000000000ChangeLog for smooth 30.12.99 18:04 - smooth alpha 0.1.5.1 - window.cpp - Neue Funktion SetPeekProc() - winapp.cpp - Peek Funktionen integriert 30.12.99 15:32 - smooth alpha 0.1.5.0 - iconbar.cpp - SMOOTHIconbar Objekt integriert - window.cpp - Anpassungen für SMOOTHIconbar - client.cpp - Anpassungen für SMOOTHIconbar - menu.cpp - Änderung der SMOOTHMenu Konstanten - stk.cpp - Neue Funktion LoadIconbarIcon() - Änderungen für SMOOTHBackgroundColor 29.12.99 19:23 - smooth alpha 0.1.4.2 - RecArray auf Version 0.8.7.0 upgedatet 29.12.99 19:12 - smooth alpha 0.1.4.1 - menubar.cpp - SMOOTHMenubar Objekt integriert - client.cpp - Anpassungen für SMOOTHMenubar - window.cpp - Anpassungen für SMOOTHMenubar - Fehlerkorrektur beim Umgang mit SMOOTHClient Objekten - titlebar.cpp - Anpassungen für SMOOTHMenubar - menu.cpp - Vervollständigung der AddMenuEntry() und RemoveMenuEntry() Funktionen - menuentry.cpp - Anpassung an Änderungen in menu.cpp - recarray.cpp - Fehler in AddEntry(t, int) behoben 29.12.99 16:56 - smooth alpha 0.1.4.0 - Optimierungslevel wieder auf 6 gesetzt, dafür Architektur auf i568 heruntergesetzt 28.12.99 20:13 - smooth alpha 0.1.3.1 - window.cpp - Abarbeitung der WM_ACTIVATEAPP (SS_APPTOPMOST) Message korrigiert 28.12.99 15:44 - smooth alpha 0.1.3.0 - client.cpp - SMOOTHClient Objekt integriert - window.cpp - 3 neue Fensterstile: SS_MODAL - Fenster bleibt innerhalb der Anwendung aktiv, SS_SYSMODAL - bleibt immer aktiv, SS_APPTOPMOST - bleibt innerhalb der Anwendung oben - Unterstützung für Clientbereiche - menu.cpp - SMOOTHMenu Objekt integriert - menuentry.cpp - SMOOTHMenuEntry Objekt als Subklasse von SMOOTHMenu integriert 27.12.99 22:10 - smooth alpha 0.1.2.5 - Todo und globals.txt upgedatet 27.12.99 20:38 - smooth alpha 0.1.2.4 - window.cpp - Wenn kein Maximierungsbutton existiert kann die Fenstergröße jetzt nicht mehr verändert werden - Unterstützung für Icons - Fenstertitel kann jetzt geändert werden - titlebar.cpp - Unterstützung für Icons - stk.cpp - Fehler behoben, der das exportieren von Funktionen verhinderte 27.12.99 19:16 - smooth alpha 0.1.2.3 - window.cpp - Trennbalken integriert - titlebar.cpp - Benutzt jetzt intensiver Farbkonstanten - Neue Toolkit Version integriert 27.12.99 18:57 - smooth alpha 0.1.2.2 - window.cpp - nOfWindows in nOfActiveWindows umbenannt und In- bzw. Dekrementierungsmodus verändert - Programm entfernt sich nun auch bei mehreren Fenstern problemlos aus der Taskliste (nein, ich meine nicht Taskleiste!!!) 27.12.99 18:42 - smooth alpha 0.1.2.1 - statusbar.cpp - SMOOTHStatusbar Objekt integriert - window.cpp - Anpassungen für SMOOTHStatusbar 27.12.99 16:59 - smooth alpha 0.1.2.0 - titlebar.cpp - SMOOTHTitlebar Objekt integriert - container.cpp - Register und Unregister Funktionen jetzt virtuell - window.cpp - Anpassungen für SMOOTHTitlebar - Eigene Register und Unregister Funktionen - application.cpp - Eigene Register und Unregister Funktionen - stk.cpp - Neue Funktion GetSMOOTHWindow(int) (by handle aka index) - Neue Funktion Affected(SMOOTHObject *, RECT &) - prüft, ob sich das Objekt im Bereich von RECT befindet 26.12.99 18:08 - smooth alpha 0.1.1.0 - Versionsnummer auf 0.1 erhöht, da die DLL jetzt einsetzbar ist 26.12.99 18:06 - smooth alpha 0.0.8.1 - window.cpp - Fenster können jetzt angezeigt und geschlossen werden - Fehler in wndclass Initialisierung behoben - Process Funktion erweitert - winapp.cpp - loopActive Variable hinzugefügt 26.12.99 16:55 - smooth alpha 0.0.8.0 - container.cpp - neue Klasse - enthält Kontainer Funktionen - Anpassungen in anderen Klassen - RecArray auf Version 0.8.6.0 upgedatet 25.12.99 11:11 - smooth alpha 0.0.7.0 - window.cpp - Create() und Process() hinzugefügt - stk.cpp - neue Datei - enthält Hilfsfunktionen 24.12.99 15:22 - smooth alpha 0.0.6.2 - window.cpp - Funktionen aus smooth 0.8.13.1 hinzugefügt - object-manager.cpp - wird jetzt nicht mehr exportiert 24.12.99 14:49 - smooth alpha 0.0.6.1 - window.cpp - Klasse in neue Struktur integriert - winapp.cpp - Datei smooth-app.cpp aus smooth 0.8.13.1 übernommen - Fehler behoben 24.12.99 13:14 - smooth alpha 0.0.6.0 - application.cpp - Klasse in neue Struktur integriert - object-manager.cpp - Klasse umstrukturiert - object.cpp - Klasse umstrukturiert 14.12.99 19:45 - smooth alpha 0.0.5.0 - window.cpp - Klasse entfernt - application.cpp - Klasse entfernt - toolkit.cpp - Anpassungen an GCC 2.95.2 - object-manager.cpp - Klasse hinzugefügt - dllmain.cpp - Initialisierung für ObjectManager hinzugefügt - libiolib.a - neue Version der IOLibrary 01.12.99 15:01 - smooth alpha 0.0.4.0 - window.cpp - Funktion Show hinzugefügt um den ShowState zu ändern 20.10.99 18:03 - smooth alpha 0.0.3.4 - application.cpp - Funktion AddObject hinzugefügt 20.10.99 17:28 - smooth alpha 0.0.3.3 - window.cpp - Objekt SMOOTHWindow hinzugefügt 20.10.99 17:08 - smooth alpha 0.0.3.2 - application.cpp - Objekt SMOOTHApplication hinzugefügt - toolkit.cpp - Toolkit hinzugefügt 20.10.99 16:42 - smooth alpha 0.0.3.1 - libiolib.a - IOLib integriert 20.10.99 16:28 - smooth alpha 0.0.3.0 - i18n.cpp - Internationalisierungsdateien hinzugefügt 19.10.99 18:23 - smooth alpha 0.0.2.1 - recarray.h - RecArray Klassen in Projekt integriert - object.cpp - Array, das alle Objekte enthält, hinzugefügt 19.10.99 18:04 - smooth alpha 0.0.2.0 - object.cpp - Objekt SMOOTHObject hinzugefügt - definitions.cpp - Datei für Definitionen hinzugefügt 02.10.99 17:54 - smooth alpha 0.0.1.2 - version.rc - Resource für Versionsinformationen hinzugefügt - linkhand.rc - Resource für Hyperlinks hinzugefügt 02.10.99 17:04 - smooth alpha 0.0.1.1 - dllmain.cpp - Initialisierungsfunktion hinzugefügt 02.10.99 16:25 - smooth alpha 0.0.1.0 - Start des 3. Rewrites von smooth smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2000000066400000000000000000001341121516402577000226100ustar00rootroot00000000000000ChangeLog for smooth 27.12.00 21:56 - smooth alpha 0.8.35.1 - Fehler in mpToolkit behoben - Progressive Setup upgedatet 27.12.00 18:49 - smooth alpha 0.8.35.0 - Versionsinformationen upgedatet - IOLib auf Version 3.9.9.0 aktualisiert 29.11.00 18:22 - smooth alpha 0.8.34.0 - combobox.cpp - Grafikfehler behoben - editbox.cpp - Geschwindigkeitsverbesserungen - Fehler behoben - objectproperties.cpp - checked und clicked sind jetzt Eigenschaften von SMOOTHObjectProperties - button.cpp - Anpassungen - object.cpp - Erweiterungen in SetText(); 28.11.00 22:38 - smooth alpha 0.8.33.2 - window.cpp - neuer Fensterstil: SS_TOOLWINDOW - toolwindow.cpp - ToolWindows sind jetzt SS_TOOLWINDOW 28.11.00 20:43 - smooth alpha 0.8.33.1 - toolwindow.cpp - ToolWindows sind jetzt SS_APPTOPMOST 28.11.00 20:30 - smooth alpha 0.8.33.0 - toolwindow.cpp - neue Datei: intern verwendete Fenster für abreissbare Menüs etc - window.cpp - Anpassungen - Messages werden jetzt an ToolWindows weitergeleitet - stk.cpp - Fehler behoben, der dazu führte, dass MDIWindows und ToolWindows nicht als Fenster angesehen wurden - objectinfo.cpp - Anpassungen - combobox.cpp - benutzt jetzt ToolWindow um ListBox anzuzeigen - toolkit.cpp - neue Funktionen: GetContext, FreeContext - alle Vorkommen von GetWindowDC durch GetContext ersetzt - IOLib auf Version 3.3 upgedatet 21.11.00 20:19 - smooth alpha 0.8.32.0 - toolkit.cpp - neue Funktionen: GetContext(), FreeContext() - Anpassungen an einigen Objekten 20.11.00 21:11 - smooth alpha 0.8.31.0 - toolkit.cpp - weitere Funktionen nach Linux portiert - CreateBitmapInfo Funktion entfernt - hyperlink.cpp - Bitmap-Link wertet jetzt SIZE Parameter aus - bitmap.cpp - Konstruktor übernimmt jetzt auch SIZE Parameter - einige (int)'s durch rounds() ersetzt 19.11.00 21:11 - smooth alpha 0.8.30.0 - scrollbar.cpp - Fehler behoben, der dazu führte, dass Elemente hinter einer ComboBox den Focus bekommen konnten - object.cpp - Fehler in Process() behoben - editbox.cpp - Start des Rewrites des EditBox Objekts - toolkit.cpp - Fehler in GetTextSizeX() behoben - colordlg.cpp - Dialog an kleine Schriften angepasst - Fehler in PaintProc behoben 18.11.00 18:12 - smooth alpha 0.8.29.0 - viele Anpassungen für Linux - alle Klassen im Verzeichnis classes/basic funktionieren jetzt unter Linux 17.11.00 18:07 - smooth alpha 0.8.28.0 - server.cpp - Port wird jetzt richtig gespeichert - definitions.cpp - typedefs für RECT, POINT und SIZE auf nicht-Windows Systemen hinzugefügt - Vorbereitungen für den Linux Port - windows.h wird jetzt von definitions.h eingebunden - Libraries lassen sich jetzt unter Linux kompilieren. FSTools, libPicture und mpToolkit sind dort allerdings nicht vollständig 16.11.00 18:00 - smooth alpha 0.8.27.0 - serverdlg.cpp - Passwortdialog an neues Layeroffset angepasst - window.cpp - Fehler behoben, der dazu führte, dass ein Programm auch nach Bestätigung nicht mit einer älteren smooth Version gestartet werden konnte 15.11.00 21:06 - smooth alpha 0.8.26.0 - andere Libraries in den Source Tree integriert - smooth wird jetzt unter der "Artistic License" veröffentlicht - Copyright Informationen zu allen Code Dateien hinzugefügt 12.11.00 19:14 - smooth alpha 0.8.25.1 - combobox.cpp - ListBox-Offset korrigiert - register.cpp - Fehler behoben - Tracing wird jetzt nicht mehr mitkompiliert 12.11.00 17:32 - smooth alpha 0.8.25.0 - window.cpp - Fehler beim Deregistrieren von Layern behoben - register.cpp - Layeroffset und -größe korrigiert - metrics.cpp - Defaulthöhe von ListBoxen angepasst - scrollbar.cpp - 'oldstyle'-Konstruktor entfernt - listbox.cpp - 'oldstyle'-Konstruktor entfernt - ScrollbarProc ist jetzt Member-Funktion - combobox.cpp - ListBoxProc ist jetzt Member-Funktion 09.11.00 16:55 - smooth alpha 0.8.24.0 - combobox.cpp - Darstellungsfehler behoben - colordlg.cpp - kleine Geschwindigkeitsverbesserungen 08.11.00 21:09 - smooth alpha 0.8.23.1 - i18n.cpp - neue Funktion SMOOTHGetDefaultLanguage() - Standardsprache wird jetzt automatisch ausgewählt 08.11.00 18:24 - smooth alpha 0.8.23.0 - window.cpp - Layeroffset und -größe korrigiert - text.cpp - Texthöhenfehler behoben - button.cpp - Texthöhenfehler behoben - listbox.cpp - Anpassungen - messagebox.cpp - Anpassungen - combobox.cpp - Anpassungen - colordlg.cpp - Geschwindigkeitsverbesserungen - Compilerwarnungen aktiviert - viele Cleanups - Anpassungen an den Dialogen 07.11.00 20:17 - smooth alpha 0.8.22.0 - editbox.cpp - SetText() benutzt jetzt GetLine - Activate() entfernt - Deactivate() entfernt - Anpassungen an Process() - Timer angepasst - scrollbar.cpp - Timer angepasst - arrows.cpp - Timer angepasst - splashscreen.cpp - Timer angepasst - divisionbar.cpp - Hide() funktioniert jetzt - client.cpp - Anpassungen - listbox.cpp - zeichnet jetzt Scrollbar neu 06.11.00 20:58 - smooth alpha 0.8.21.1 - object.cpp - Fehler in Hide() behoben - Toolkit upgedatet - Alle Sleep() Aufrufe durch Wait() ersetzt - Tracing abgeschaltet 06.11.00 19:43 - smooth alpha 0.8.21.0 - editbox.cpp - Paint() benutzt jetzt GetLine() - object.cpp - Hide() zeichnet jetzt nicht mehr auf den Desktop - Toolkit upgedatet - Fehler im Server behoben 30.10.00 20:30 - smooth alpha 0.8.20.0 - threadmanager.cpp - neue Datei: verwaltet Threads - stk.cpp - GetNewObjectID(...) heisst jetzt RequestObjectID(...) - neue Funktion: RequestObjectHandle(...) gibt ein gültiges Objekt Handle zurück - dllmain.cpp - Anpassungen - object.cpp - Anpassungen - i18n.cpp - neue Variable: TXT_ERROR_THREADMANAGEREXISTS - thread.cpp - Registriert sich jetzt beim ThreadManager - winapp.cpp - Anpassungen 29.10.00 21:43 - smooth alpha 0.8.19.0 - register.cpp - überflüssigen Code entfernt - IOLib auf Version 3.2 aktualisiert - fsTools aktualisiert - mpTrace aktualisiert - exception handling abgeschaltet 16.10.00 15:45 - smooth alpha 0.8.18.0 - object.cpp - neue Funktion: SetPosition(...); - neue Funktion: SetMetrics(...); - neue Funktion: GetTextSize(...); - Funktion SetText(...) verbessert - Funktionen Activate(...) und Deactivate(...) verbessert - Fehler behoben - button.cpp - Funktion SetText(...) entfernt - Funktion GetSize(...) entfernt - Anpassungen an neue API - checkbox.cpp - Funktion SetText(...) entfernt - objectproperties.cpp - neue Variable: SIZE tsize - metrics.cpp - Variable METRIC_BUTTONTXTHEIGHT entfernt - text.cpp - Funktion SetText(...) entfernt - Funktion GetSize(...) entfernt - Anpassungen - Multiline Fähigkeiten verbessert - slider.cpp - Funktion SetValue(...) vereinfacht - Verbesserungen - register.cpp - Verbesserungen - stk.cpp - Funktion Affected(...) verbessert - layer.cpp - Funktion Paint(...) verbessert - groupbox.cpp - Funktion SetText(...) entfernt - Funktion GetSize(...) entfernt - Anpassungen - Programm ObjTest zum Testen von smooth Objekten hinzugefügt - Progressive Setup aktualisiert - mpToolkit aktualisiert 08.10.00 16:58 - smooth alpha 0.8.17.0 - window.cpp - Grafikfehler behoben - mpToolkit aktualisiert 07.10.00 14:37 - smooth alpha 0.8.16.0 - window.cpp - kleinere Verbesserungen - editbox.cpp - Fehler behoben - i18n.cpp - neue Variable: I18N_DEFAULTFONT - objectproperties.cpp - Parameter für die Schriftart hinzugefügt - object.cpp - neue Funktion: SetFont(...); - neue Funktion: SetOrientation(...); - fontdlg.cpp - Fehler behoben - messagebox.cpp - Anpassungen - Konstruktoren übernehmen jetzt keinen OR_* Parameter mehr - Anpassungen an fast allen Objekten - Anpassungen an den Dialogen 06.10.00 16:59 - smooth alpha 0.8.15.0 - server.cpp - Befehl 129 implementiert - sessionmanagement.cpp - Fehler in SMOOTHLoadSessionData behoben - window.cpp - Fehler behoben - Dialoge können jetzt nicht mehr über das Systemmenü maximiert werden - Fenster können jetzt nicht mehr beliebig klein gezogen werden - Create() ist jetzt protected - winapp.cpp - Ruft jetzt SMOOTHWindow::Create() auf - metrics.cpp - Neue Variablen für Default- und Minimalfenstergröße - messagebox.cpp - Anpassungen - splashscreen.cpp - Anpassungen - Anpassungen am Server - Progressive Setup aktualisiert - Anpassungen an den Dialogen 05.10.00 17:34 - smooth alpha 0.8.14.0 - editbox.cpp - Grafikfehler behoben - Procs können jetzt auch in fremden Klassen liegen - Anpassungen an fast allen Objekten 04.10.00 16:30 - smooth alpha 0.8.13.0 - serverdlg.cpp - Session kann jetzt mit Passwort geschützt werden - window.cpp - Anpassungen - colordlg.cpp - Anpassungen - sessionmanagement.cpp - Befehl setPASS implementiert - server.cpp - Befehl 126 implementiert - verbessertes Verhalten von inaktiven und unsichtbaren Objekten - Anpassungen am Server - Passwörter werden jetzt verschlüsselt gespeichert und übertragen (allerdings mit sehr einfacher Verschlüsselung) 03.10.00 20:35 - smooth alpha 0.8.12.0 - window.cpp - Verbesserungen bei modalen Fenstern - server.cpp - Passwortschutz integriert - serverdlg.cpp - Passwortabfrage integriert - Server kann jetzt mit Passwort geschützt werden - IOLib auf Version 3.0a upgedatet 30.09.00 14:03 - smooth alpha 0.8.11.0 - serverdlg.cpp - Fehler behoben - stk.cpp - neue Funktion: GetSMOOTHVersion - server.cpp - Fehler behoben - winapp.cpp - Anpassungen - Anwendungen überprüfen jetzt die smooth Version und geben ggf. eine Warnung aus - Anpassungen am smooth Server - mpString auf Version 0.2.13.0 aktualisiert 29.09.00 20:31 - smooth alpha 0.8.10.1 - serverdlg.cpp - erlaubt jetzt Auswahl der Session - sessionmanagement.cpp - neue Funktion: SMOOTHChooseSession (intern) - server.cpp - Anpassungen - neuer Befehl implementiert: useSESS - object.cpp - Activate und Deactivate rufen jetzt Paint auf - button.cpp - Activate und Deactivate werden jetzt unterstützt - Anpassungen am smooth Server 29.09.00 15:18 - smooth alpha 0.8.10.0 - corbamanager.cpp - durch odsmanager.cpp ersetzt - server.cpp - neuer Befehl implementiert: getDATA - neuer Befehl implementiert: sndDATA - neuer Befehl implementiert: getLIST - neuer Befehl implementiert: sndLIST - neuer Befehl implementiert: srvINIT - sessionmanagement.cpp - neue Funktion: SMOOTHSaveSessionData - neue Funktion: SMOOTHLoadSessionData - CORBA ORB entfernt - mpTrace aktualisiert - Server erweitert - Fehler im Server beseitigt 24.09.00 16:46 - smooth alpha 0.8.9.0 - client.cpp - geometrische Fehler behoben - serverdlg.cpp - Layout fertiggestellt - winapp.cpp - Anpassungen - dialogproperties.cpp - neue Variablen für Server Dialog - Sprachunterstützung verbessert - Progressive Setup aktualisiert - Tutorial hinzugefügt - IOLib auf Version 3.0 aktualisiert - mpString auf Version 0.2.12.0 aktualisiert - fsTools aktualisiert - Server erweitert 21.09.00 20:50 - smooth alpha 0.8.8.0 - corbamanager.cpp - neue Datei: Funktionen zur Steuerung des CORBA Interfaces - serverdlg.cpp - neue Datei: Dialog zur Serverauswahl - server.cpp - neue Datei: Funktionen zur Steuerung des smooth Servers - neuer Befehl implementiert: getHOST - neuer Befehl implementiert: getINFO - thread.cpp - Fehler #0012 behoben - winapp.cpp - Anpassungen - mpString auf Version 0.2.11.0 upgedatet - fsTools upgedatet - mpTrace upgedatet - IOLib auf Version 3.0-pre4 aktualisiert 13.09.00 18:42 - smooth alpha 0.8.7.0 - verbesserte Sprachunterstützung - CORBA Bibliothek integriert 08.09.00 16:24 - smooth alpha 0.8.6.0 - hyperlink.cpp - unterstützt jetzt auch Bitmaps 06.09.00 18:05 - smooth alpha 0.8.5.0 - thread.cpp - Thread Objekt ist jetzt ein SMOOTHObject - ThreadProc übernimmt jetzt einen SMOOTHThread - application.cpp - Anpassungen - mpString auf Version 0.2.10.0 aktualisiert - FSTools aktualisiert 05.09.00 20:17 - smooth alpha 0.8.4.2 - thread.cpp - neue Klasse: SMOOTHThread - Kapselung für Windows Threads - application.cpp - neue Funktionen: RegisterThread un UnregisterThread - definitions.cpp - neues Makro: SMOOTHExitThread(); 05.09.00 17:57 - smooth alpha 0.8.4.1 - mpString auf Version 0.2.9.2 aktualisiert - fsTools aktualisiert 05.09.00 16:36 - smooth alpha 0.8.4.0 - IOLib auf Version 3.0-pre3 aktualisiert - mpString auf Version 0.2.9.0 aktualisiert - mpTrace aktualisiert - fsTools auf Version 0.1.4.0 aktualisiert - Anpassungen 31.08.00 20:39 - smooth alpha 0.8.3.0 - titlebar.cpp - Fehler in SetText() behoben - optionbox.cpp - Verbesserungen - bessere Sprachunterstützung 23.08.00 20:29 - smooth alpha 0.8.2.2 - mdiwindow.cpp - Anpassungen - object.cpp - Verbesserungen in Show(); - stk.cpp - neue Funktion: GetRealPosition(); - button.cpp - Verbesserungen - text.cpp - Verbesserungen - Progressive Setup upgedatet - Archivformat für Setup ist jetzt bzip2 23.08.00 12:50 - smooth alpha 0.8.2.1 - sessionmanagement.cpp - neue Funktion: EnableSessionManagement(); - stk.cpp - Funktion GetSMOOTHWindow(HWND) wird jetzt nicht mehr exportiert - Funktion SMOOTHCloseWindow(HWND) entfernt - titlebar.cpp - Anpassungen - statusbar.cpp - Anpassungen - iconbar.cpp - Anpassungen - menubar.cpp - Anpassungen - definitions.cpp - Fehler in NULLKillProc behoben - objectinfo.cpp - Anpassungen - mdiwindow.cpp - neue Klasse: Fenster, in dem MDI Daten angezeigt werden - SessionManagement ist jetzt per default aus - bessere Sprachunterstützung 23.08.00 10:33 - smooth alpha 0.8.2.0 - Progressive Setup upgedatet - UPX Packer integriert 22.08.00 18:20 - smooth alpha 0.8.1.1 - window.cpp - SMOOTHWindow(); entfernt - Fensterklasse hat jetzt den Namen des Fensters - mdiclient.cpp - neue Klasse: Clientbereich für MDI Parents - verbesserte Sprachunterstützung - Progressive Setup upgedatet - neues Verzeichnis: classes/mdi - enthält Klassen für Multiple Document Interface - neues Beispiel: MDITest 22.08.00 13:50 - smooth alpha 0.8.1.0 - treeview.cpp - vollständige Unterstützung für große Schriften - combobox.cpp - vollständige Unterstützung für große Schriftarten - editbox.cpp - vollständige Unterstützung für große Schriftarten - arrows.cpp - Fehler behoben - metrics.cpp - Anpassungen - Versionsnummer auf 0.8 erhöht 21.08.00 22:42 - smooth alpha 0.7.37.1 - register.cpp - vollständig an kleine Schriftarten angepasst - arrows.cpp - Unterstützung für kleine Schriftarten verbessert - i18n.cpp - neue Variablen - welsh.cpp - neue Sprache: Walisisch - bessere Sprachunterstützung 21.08.00 19:08 - smooth alpha 0.7.37.0 - object.cpp - Anpassungen und einige neue virtuelle Funktionen für neue API - Anpassungen an fast allen Objekten 20.08.00 21:54 - smooth alpha 0.7.36.2 - titlebar.cpp - kleineren Fehler behoben - server.cpp - ist jetzt beim Start unsichtbar - window.cpp - kleine Anpassungen - messagebox.cpp - Anpassungen - listbox.cpp - Anpassungen - combobox.cpp - Anpassungen 20.08.00 13:54 - smooth alpha 0.7.36.1 - register.cpp - bessere Anpassung an kleine Schriftarten - scrollbar.cpp - bessere Anpassung an kleine Schriftarten - slider.cpp - bessere Anpassung an kleine Schriftarten - editbox.cpp - bessere Anpassung an kleine Schriftarten - bitmap.cpp - vollständige Anpassung an kleine Schriftarten - metrics.cpp - neue Variablen 20.08.00 12:39 - smooth alpha 0.7.36.0 - stärkere Objektorientierung (Anwendungen sind Objekte) wie in KDE - zahlreiche Änderungen zur Anpassung an neue API 16.08.00 16:59 - smooth alpha 0.7.35.1 - window.cpp - neue Funktion: SetPositionFlag(HWND); - server.cpp - ist jetzt eine smooth Anwendung - winapp.cpp - neue Funktion: SMOOTHFreeResources(); - sessionmanagement.cpp - ist jetzt multithreaded - Neue Resource: IDB_ICON - Neue Resource: IDI_ICON 16.08.00 12:27 - smooth alpha 0.7.35.0 - server.cpp - ist jetzt multithreaded - Erweiterungen - winapp.cpp - Meldung, wenn Verbindung zum Server fehlschlägt - ruft jetzt automatisch wnd->Show() auf - sessionmanagement.cpp - Erweiterungen 14.08.00 16:13 - smooth alpha 0.7.34.0 - server.cpp - smooth Server für Sessionmanagement hinzugefügt 13.08.00 22:23 - smooth alpha 0.7.33.0 - neues Verzeichnis: tools für smooth server - IOLib auf Version 3.0-pre1 upgedatet - mpTrace aktualisiert - FSTools aktualisiert 11.08.00 12:37 - smooth alpha 0.7.32.0 - IOLib auf Version 2.9.6.0 upgedatet - mpTrace aktualisiert - FSTools aktualisiert 10.08.00 14:26 - smooth alpha 0.7.31.0 - window.cpp - Vollständige Anpassung an klein/große Schriftarten - progressbar.cpp - Vollständige Anpassung an klein/große Schriftarten - divisionbar.cpp - Vollständige Anpassung an klein/große Schriftarten - listbox.cpp - Vollständige Anpassung an klein/große Schriftarten - metrics.cpp - neue Variablen - Kit Includes sind jetzt im Unterverzeichnis smooth 09.08.00 20:01 - smooth alpha 0.7.30.0 - filedlg.cpp - gibt jetzt absoluten Dateinamen zurück - activearea.cpp - Vollständige Anpassung an klein/große Schriftarten - checkbox.cpp - Vollständige Anpassung an klein/große Schriftarten - optionbox.cpp - Vollständige Anpassung an klein/große Schriftarten - groupbox.cpp - Vollständige Anpassung an klein/große Schriftarten - button.cpp - Vollständige Anpassung an klein/große Schriftarten - text.cpp - Vollständige Anpassung an klein/große Schriftarten - hyperlink.cpp - Vollständige Anpassung an klein/große Schriftarten - metrics.cpp - neue Variablen - Status Log eingeführt - FSTools auf Version 0.1.3.0 upgedatet 07.08.00 21:16 - smooth alpha 0.7.29.1 - Toolkit upgedatet - Setup upgedatet 07.08.00 15:47 - smooth alpha 0.7.29.0 - Nutzung von mpString fast überall - erhöht möglicherweise Stabilität und Speichersicherheit - mpString ist jetzt Bestandteil der libsmooth.a 06.08.00 20:22 - smooth alpha 0.7.28.1 - dialogproperties.cpp - neue Variable: dir - filedlg.cpp - Title ist jetzt string statt char * - dirdlg.cpp - Title ist jetzt string statt char * - fontdlg.cpp - Title ist jetzt string statt char * - messagebox.cpp - text kann jetzt auch NULL sein 06.08.00 16:06 - smooth alpha 0.7.28.0 - treeview.cpp - Funktionierende PaintTree() Funktion - Funktionen: AddEntry(...) und RemoveEntry(int) entfernt - tree.cpp - Add- und Remove-Funktionen aus TreeView übernommen - Add-Funktion übernimmt jetzt zusätzliche bool Variable, die angibt ob der Tree geöffnet ist 05.08.00 20:48 - smooth alpha 0.7.27.1 - combobox.cpp - Fehler behoben, der dazu führte, dass procs nicht ausgeführt wurden - filedlg.cpp - jetzt funktionsfähig - list.cpp - neue Funktion: GetSelectedEntryName() - neue Funktion: Cleanup() - FSTools auf Version 0.1.2.1 upgedatet - Geometrische Verbesserungen an den Dialogen 05.08.00 18:38 - smooth alpha 0.7.27.0 - listbox.cpp - Fehler #0011 behoben - dialogproperties.cpp - neue Klasse: kapselt Dialogeigenschaften - dialogs.cpp - Anpassungen an SMOOTHDialogProperties - alle Dialoge übernehmen jetzt SMOOTHDialogProperties als einzigen Parameter 04.08.00 20:28 - smooth alpha 0.7.26.1 - combobox.cpp - verhält sich jetzt wie Windows ComboBox - filedlg.cpp - Erweiterungen - Toolkit upgedatet 04.08.00 12:39 - smooth alpha 0.7.26.0 - Progressive Setup auf Version 0.0.4.1 upgedatet - mpString auf Version 0.2.8.2 upgedatet - FSTools Version 0.1.1.0 integriert 02.08.00 20:03 - smooth alpha 0.7.25.1 - combobox.cpp - aktiver Eintrag kann jetzt auch ausgewählt werden - listbox.cpp - neue Variable: allowreselect 02.08.00 17:33 - smooth alpha 0.7.25.0 - Progressive Setup Dateien upgedatet - Umwandlung in ein SourceNavigator Projekt 12.07.00 19:26 - smooth alpha 0.7.24.1 - metrics.cpp - Schriftgröße angepasst 12.07.00 18:54 - smooth alpha 0.7.24.0 - combobox.cpp - listbox wird jetzt auf NULL überprüft (Fehler #0010) 07.07.00 15:45 - smooth alpha 0.7.23.0 - combobox.cpp - Hintergrund wird jetzt gesichert und neu gezeichnet (Fehler #0009) - Ereignisprozedur vereinfacht - listbox.cpp - Ereignisprozedur vereinfacht 06.07.00 18:06 - smooth alpha 0.7.22.0 - combobox.cpp - dynamische Größenanpassung - listbox.cpp - Rechenfehler behoben 05.07.00 14:32 - smooth alpha 0.7.21.1 - window.cpp - Zeichnet jetzt ganzes Fenster neu, wenn WM_PAINT wParam == 0 05.07.00 12:56 - smooth alpha 0.7.21.0 - bitmap.cpp - neue Funktion: UpdateBitmap 26.06.00 11:21 - smooth alpha 0.7.20.0 - definitions.cpp - neue Funktion: KILLPROC gibt bool zurück - window.cpp - killproc wird jetzt bei WM_CLOSE ausgeführt - Ergebnis von killproc wird ausgewertet - stk.cpp - neue Funktion: SMOOTCloseWindow - titlebar.cpp - benutzt jetzt SMOOTHCloseWindow - Dialoge benutzen jetzt SMOOTHCloseWindow - RecArray upgedatet 19.06.00 13:36 - smooth alpha 0.7.19.0 - colordlg.cpp - Geschwindigkeitsverbesserungen 18.06.00 17:41 - smooth alpha 0.7.18.0 - winapp.cpp - drei neue Farbkonstanten für Textfarbe - Farben werden jetzt nicht mehr selbst berechnet - Anpassungen an vielen Objekten - Toolkit upgedatet 17.06.00 21:17 - smooth alpha 0.7.17.0 - winapp.cpp - vier neue Farbvariablen hinzugefügt - window.cpp - benutzt jetz Standard-Brush - Farbanpassungen in vielen Objekten - Toolkit upgedatet 16.06.00 17:43 - smooth alpha 0.7.16.0 - winapp.cpp - Tracefile ist jetzt NULL - messagebox.cpp - Vollständig an kleine Schriftarten angepasst - metrics.cpp - neue Variable: METRIC_SMALLFONTSIZE - window.cpp - hCursor wird jetzt mit NULL initialisiert - Anpassungen an kleine bzw. große Schriftarten in vielen Objekten - IOLib auf Version 2.9.5.0 upgedatet 07.06.00 20:29 - smooth alpha 0.7.15.1 - IOLib auf Version 2.9.4.1 upgedatet - mpTrace auf Version 0.6.2 upgedatet 07.06.00 17:48 - smooth alpha 0.7.15.0 - window.cpp - Process() ist jetzt public - definitions.cpp - neue Message SM_LOOSEFOCUS - combobox.cpp - reagiert jetzt auf SM_LOOSEFOCUS Message (Fehler #0003) - sendet SM_LOOSEFOCUS - editbox.cpp - reagiert auf SM_LOOSEFOCUS - listbox.cpp - sendet SM_LOOSEFOCUS bei WM_LBUTTONDOWN - menubar.cpp - sendet SM_LOOSEFOCUS - iconbar.cpp - sendet SM_LOOSEFOCUS - window.cpp - sendet SM_LOOSEFOCUS - IOLib auf Version 2.9.4.0 upgedatet 06.06.00 21:05 - smooth alpha 0.7.14.0 - window.cpp - hCursor Feld von WNDCLASSEX wird jetzt initialisiert (Fehler #0008) - Kompatibilitätsprobleme mit Windows NT Build 2195 (Windows 2000 Professional) behoben 30.05.00 19:43 - smooth alpha 0.7.13.1 - metrics.cpp - neue Konstanten - button.cpp - vollständige Anpassung an kleine Schriften - besitzt jetzt Defaultbreite 30.05.00 15:20 - smooth alpha 0.7.13.0 - IOLib auf Version 2.9.3.0 upgedatet - mpTrace upgedatet 29.05.00 15:24 - smooth alpha 0.7.12.0 - editbox.cpp - Returns werden jetzt korrekt gelöscht 28.05.00 15:20 - smooth alpha 0.7.11.1 - editbox.cpp - einige Anpassungen für Multiline Modus 28.05.00 14:59 - smooth alpha 0.7.11.0 - window.cpp - WM_GETMINMAXINFO Reaktion durch WM_SETTINGCHANGE ersetzt 26.05.00 19:04 - smooth alpha 0.7.10.0 - mpString upgedatet 22.05.00 22:19 - smooth alpha 0.7.9.0 - window.cpp - reagiert jetzt auf WM_GETMINMAXINFO Nachricht - editbox.cpp - neue Variable currline - Variable tsize entfernt - Anpassungen - titlebar.cpp - maximized is jetzt public 16.05.00 18:25 - smooth alpha 0.7.8.0 - binary.cpp - Fehler in IsBitSet behoben - editbox.cpp - Fehler behoben - Multiline Fähigkeit integriert (pre-alpha) - IOLib upgedatet 05.05.00 17:16 - smooth alpha 0.7.7.0 - editbox.cpp - erste Anpassungen für Multiline Editboxen - winapp.cpp - Tracing deaktiviert - mpTrace upgedatet - mpString upgedatet 04.05.00 20:24 - smooth alpha 0.7.6.1 - splashscreen.cpp - Anzeigeoptionen verändert - SMOOTHSplashScreen übernimmt jetzt Prozedur als dritten Parameter - client.cpp - optische Verbesserungen 04.05.00 18:20 - smooth alpha 0.7.6.0 - window.cpp - neue Stilkonstante: SS_NORESIZE - splashscreen.cpp - neue Datei: stellt SplashScreens zur Verfügung - stk.cpp - neue Funktion: GetSMOOTHSplashScreen - kleinere Verbesserungen 03.05.00 17:25 - smooth alpha 0.7.5.2 - groupbox.cpp - weitere Anpassungen - metrics.cpp - neue Konstanten - kleine Fehler behoben - popupmenu.cpp - teilweise Anpassung an kleine Schriftarten - menu.cpp - weitere Anpassungen 03.05.00 14:38 - smooth alpha 0.7.5.1 - groupbox.cpp - vollständige Anpassung an kleine Schriftarten - hyperlink.cpp - vollständige Anpassung an kleine Schriftarten - messagebox.cpp - Anpassungen an kleine Schriftarten - Anpassungen an den Beispielen 03.05.00 14:10 - smooth alpha 0.7.5.0 - statusbar.cpp - vollständige Anpassung an kleine Schriftarten - client.cpp - Anpassungen 02.05.00 17:25 - smooth alpha 0.7.4.0 - metrics.cpp - neue Konstanten - menubar.cpp - vollständige Anpassung an kleine Schriftarten - optische Verbesserungen - window.cpp - Anpassungen - client.cpp - Anpassungen - divisionbar.cpp - Anpassungen - iconbar.cpp - vollständige Anpassung an kleine Schriftarten - optische Fehler behoben - menu.cpp - vollständige Anpassung an kleine Schriftarten 25.04.00 19:43 - smooth alpha 0.7.3.0 - metrics.cpp - Variablen werden jetzt exportiert - neue Funktion: SMOOTHSetMeasurement() - lithuanian.cpp - neue Sprache: Litauisch - tamil.cpp - neue Sprache: Tamilisch - ukrainian.cpp - neue Sprache: Ukrainisch - i18n.cpp - Anpassungen 19.04.00 17:39 - smooth alpha 0.7.2.0 - objectmanager.cpp - mainObjectManager wird jetzt exportiert - colordlg.cpp - Geschwindigkeit optimiert 18.04.00 21:14 - smooth alpha 0.7.1.2 - metrics.cpp - neue Konstanten definiert - titlebar.cpp - Anpassungen an neue Metrics-Definitionen - vollständig an kleine Schriftarten angepaßt - stk.cpp - Funktion DownscaleSMOOTHIcon() entfernt - neue mpToolkit eingefügt 18.04.00 15:17 - smooth alpha 0.7.1.1 - window.cpp - erzeugt jetzt für jede Application eine eigene Fensterklasse - colordlg.cpp - Geschwindigkeitsverbesserungen 18.04.00 09:41 - smooth alpha 0.7.1.0 - editbox.cpp - drei neue Konstanten hinzugefügt: EDB_MULTILINE, EDB_HSCROLL, EDB_VSCROLL - toolkit.h aus den kit include-Dateien entfernt - Versionsnummer auf 0.7 erhöht 17.04.00 18:36 - smooth alpha 0.6.28.2 - Änderungen an den kit include-Dateien - Erweiterungen an der BeatClock 17.04.00 14:50 - smooth alpha 0.6.28.1 - object.cpp - objinfo ist jetzt protected statt private - PlugIn Beispiel erweitert - kit include-Dateien upgedatet 17.04.00 10:26 - smooth alpha 0.6.28.0 - objectinfo.cpp - neue Funktionen: SetContainerFlag(), SetRegisterFlag(); - Plugin API vollständig integriert 16.04.00 20:50 - smooth alpha 0.6.27.1 - Pluginschnittstelle integriert - neues Beispiel hinzugefügt: Plugin 16.04.00 17:18 - smooth alpha 0.6.27.0 - nicht benötigte Daten werden jetzt aus der Import Library entfernt 14.04.00 19:44 - smooth alpha 0.6.26.2 - stk.cpp - neue Funktion: DownscaleSMOOTHIcon() verkleinert ein Icon von 20 auf 16 QPixel - editbox.cpp - Darstellungsfehler behoben - statusbar.cpp - Darstellungsfehler behoben 14.04.00 18:21 - smooth alpha 0.6.26.1 - metrics.cpp - neue Datei - enthält Geometriekonstanten - titlebar.cpp - benutzt jetzt metrics.cpp - window.cpp - (0, 0)-Position von Layern ist jetzt unterhalb der Menüleisten - Anpassungen an fast allen Dateien 14.04.00 16:39 - smooth alpha 0.6.26.0 - layer.cpp - Fehler behoben - treeview.cpp - Übernimmt jetzt Tree-Namen im Konstruktor - scrollbar.cpp - Fehler behoben - arrows.cpp - Fehler behoben 13.04.00 20:15 - smooth alpha 0.6.25.1 - object.cpp - virtuelle Funktion Show() hinzugefügt - virtuelle Funktion Hide() hinzugefügt - virtuelle Funktion Activate() hinzugefügt - virtuelle Funktion Deactivate() hinzugefügt - Variable visible (bool) hinzugefügt - Variable active (bool) hinzugefügt - window.cpp - Anpassungen - macht Layer beim registrieren sichtbar - layer.cpp - Anpassungen - editbox.cpp - Wertet jetzt active Variable aus - register.cpp - Layerverwaltung verändert 13.04.00 17:16 - smooth alpha 0.6.25.0 - treeview.cpp - diverse Erweiterungen - neue Funktion: PaintTree() - treeentry.cpp - Änderungen in der Verwaltung - neue Variable: open (bool) gibt an, ob ein Untereintrag offen ist - neue Variable: last (bool) gibt an, ob weitere Einträge folgen - listentry.cpp - Änderungen in der Verwaltung - menuentry.cpp - Änderungen in der Verwaltung - tree.cpp - Anpassungen - list.cpp - Anpassungen - menu.cpp - Anpassungen 07.04.00 16:53 - smooth alpha 0.6.24.0 - dirdlg.cpp - neuer Dialog: Verzeichnisauswahl - fontdlg.cpp - neuer Dialog: Schriftauswahl - i18n.cpp - neue Strings für neue Dialoge 05.04.00 14:35 - smooth alpha 0.6.23.0 - IOLib und mpTrace upgedatet 02.04.00 17:15 - smooth alpha 0.6.22.1 - Jetzt können auch DLLs geschrieben werden, die smooth benutzen. SMOOTHMain() heisst dann SMOOTHEntry(). Sie benötigen smoothdll.h statt smooth.h 02.04.00 12:27 - smooth alpha 0.6.22.0 - mathtools.cpp - round() Funktion verbessert - messagebox.cpp - Fehler bei der Deregistrierung von Buttons behoben 25.03.00 15:33 - smooth alpha 0.6.21.2 - objectproperties.cpp - hält jetzt 'pos', 'size' und 'orientation' Attribute - object.cpp - Attribute entfernt - Anpassungen an den meisten Objekten 25.03.00 13:53 - smooth alpha 0.6.21.1 - objectproperties.cpp - hält jetzt 'text' Attribut - object.cpp - 'text' Attribut entfernt - neue Funktion: GetObjectProperties(); - Anpassungen an fast allen Objekten 25.03.00 13:09 - smooth alpha 0.6.21.0 - objectproperties.cpp - neue Klasse: enthält Objekteigenschaften - object.cpp - benutzt jetzt SMOOTHObjectProperties - objectmanager.cpp - Datei object-manager.cpp umbenannt 22.03.00 18:15 - smooth alpha 0.6.20.0 - colordlg.cpp - Geschwindigkeitsverbesserungen 20.03.00 20:23 - smooth alpha 0.6.19.1 - HTML Dokumente in die Distribution aufgenommen - neue Strings für Dateidialoge 20.03.00 15:30 - smooth alpha 0.6.19.0 - Setuproutinen hinzugefügt 19.03.00 14:12 - smooth alpha 0.6.18.2 - neue mpString Version integriert 19.03.00 13:13 - smooth alpha 0.6.18.1 - arrows.cpp - Process() gibt jetzt rval zurück - filedlg.cpp - Buttons und Divisionbar hinzugefügt 19.03.00 12:32 - smooth alpha 0.6.18.0 - filedlg.cpp - neuer Standarddialog: Dateiauswahl - dialogs.cpp - Anpassungen an neuen Dialog - i18n.cpp - neue Strings hinzugefügt 18.03.00 19:06 - smooth alpha 0.6.17.1 - treeview.cpp - neues Objekt: TreeView - objectinfo.cpp - Anpassungen an neues Objekt - object.cpp - Definition OBJ_TREEVIEW hinzugefügt 18.03.00 16:26 - smooth alpha 0.6.17.0 - list.cpp - neue Funktion SelectEntry() - listbox.cpp - scroll wird jetzt nach benutzung ordnungsgemäß gelöscht - Paint() ruft jetzt scroll->Paint() auf - Process() setzt jetzt rval korrekt - combobox.cpp - Implementierung vervollständigt - einige Fehler behoben - scrollbar.cpp - Process() gibt jetzt rval zurück - layer.cpp - Process() arbeitet die Einträge jetzt rückwärts ab - Änderungen an BeatClock 17.03.00 18:20 - smooth alpha 0.6.16.3 - objectinfo.cpp - neue Funktion GetContainerFlag() - stk.cpp - Fehler in GetSMOOTHLayer() behoben - Fehler behoben, der dazu führte, dass das Programm nicht ordentlich beendet wurde 17.03.00 16:54 - smooth alpha 0.6.16.2 - menu, list, tree, hyperlink und text auf mpString umgestellt 17.03.00 16:13 - smooth alpha 0.6.16.1 - combobox.cpp - Implementierung fast vollständig (bis auf Öffnen der ListBox) - BugList hinzugefügt 17.03.00 15:04 - smooth alpha 0.6.16.0 - list.cpp - neue Funktion GetSelectedEntry() - listbox.cpp - Konstruktor übernimmt jetzt Ereignisprozedur - combobox.cpp - Konstruktor übernimmt jetzt Ereignisprozedur 13.03.00 18:54 - smooth alpha 0.6.15.1 - layer.cpp - benutzt jetzt neue Objekt Schnittstelle - register.cpp - benutzt jetzt neue Objekt Schnittstelle - application.cpp - benutzt jetzt neue Objekt Schnittstelle - container.cpp - benutzt jetzt neue Objekt Schnittstelle - objectinfo.cpp - neue Funktion Init() - Anpassungen am Header 13.03.00 15:48 - smooth alpha 0.6.15.0 - neue picture Bibliothek eingefügt - Schriftgrößenberechnung verbessert 12.03.00 20:33 - smooth alpha 0.6.14.2 - binary.cpp - zwei neue Funktionen: GetBit() und IsBitSet() - combobox.cpp - neues Objekt: ComboBox - layer.cpp - akzeptiert jetzt ComboBoxen - object.cpp - Definition OBJ_COMBOBOX hinzugefügt - objectinfo.cpp - Änderungen am Konstruktor - neue Funktion: AskContainer() - listbox.cpp - Textdarstellung unter Windows 9x verbessert 12.03.00 17:20 - smooth alpha 0.6.14.1 - listbox.cpp - Objekt fertiggestellt 12.03.00 15:01 - smooth alpha 0.6.14.0 - listbox.cpp - viele Erweiterungen - objectinfo.cpp - neue Klasse - enthält Informationen zu Objekten - object.cpp - enthält jetzt Funktionen für ObjectInfo - color.cpp - benutzt jetzt round() Funktion - slider.cpp - benutzt jetzt round() Funktion - scrollbar.cpp - benutzt jetzt round() Funktion - neue Toolkit Version 10.03.00 17:51 - smooth alpha 0.6.13.1 - mathtools.cpp - neue Datei - enthält mathematische Hilfsfunktionen - progressbar.cpp - einige int-Casts durch round() ersetzt - listbox.cpp - Änderungen am Konstruktor - Änderungen in Paint() und Process() 10.03.00 17:26 - smooth alpha 0.6.13.0 - color.cpp - Anpassungen für GCC 2.96 - listbox.cpp - neues Objekt - ListBox - layer.cpp - akzeptiert jetzt ListBoxen - object.cpp - Definition für OBJ_LISTBOX hinzugefügt 03.03.00 19:46 - smooth alpha 0.6.12.0 - maori.cpp - Unterstützung für Maori - i18n.cpp - Anpassungen an Maori Unterstützung - Libraries auf neue Versionen aktualisiert 24.02.00 12:46 - smooth alpha 0.6.11.0 - Anpassungen an GCC 2.96 16.02.00 20:38 - smooth alpha 0.6.10.1 - menubar.cpp - Unterstützt jetzt Shortcuts (mit & kennzeichnen) 16.02.00 14:37 - smooth alpha 0.6.10.0 - progressbar.cpp - Aussehen verbessert - Option der Wertanzeige integriert - Vertikale Progressbar hinzugefügt 15.02.00 11:28 - smooth alpha 0.6.9.0 - progressbar.cpp - Objekt fertiggestellt 14.02.00 15:33 - smooth alpha 0.6.8.0 - optionbox.cpp - Fehler in Process() behoben - progressbar.cpp - neues Objekt - eine Fortschrittsanzeige - layer.cpp - Akzeptiert jetzt Progressbars - neue Toolkit Version, die jetztverstärkt Binäroperationen benutzt - neue libPicture Version, die jetzt Inline Funktionen benutzt 13.02.00 19:29 - smooth alpha 0.6.7.2 - colordlg.cpp - Gibt jetzt oldcolor zurück, wenn auf Fenster schließen geklickt wird - slider.cpp - Rundungsfehler behoben - scrollbar.cpp - Rundungsfehler behoben - color.cpp - Rundungsfehler behoben 13.02.00 18:33 - smooth alpha 0.6.7.1 - colordlg.cpp - Kleinere Fehler behoben - tree.cpp - Fehler in den Header Dateien behoben - list.cpp - Basisklasse für Listen hinzugefügt - listentry.cpp - Klasse für Einträge in Listen 13.02.00 16:24 - smooth alpha 0.6.7.0 - text.cpp - Konstruktor verändert - colordlg.cpp - Fehler bei der Berechnung der RGB Werte behoben - Dialog Fertiggestellt - editbox.cpp - Konstuktor übernimmt jetzt Attribut numerisch oder alphanumerisch sowie maximale Länge - Toolkit upgedatet (neue Version enthält IntegerToString) 12.02.00 20:07 - smooth alpha 0.6.6.2 - window.cpp - 2 neue Funktionen: RECT GetUpdateRect(); void SetUpdateRect(RECT); - Paint(RECT); ist jetzt Paint(); - activearea.cpp - Anpassungen an Änderungen - titlebar.cpp - Anpassungen an Änderungen - colordlg.cpp - Benutzt jetzt direkten Speicherzugriff und UpdateRegions - Werte können jetzt verändert werden - Slider für HSVRGB hinzugefügt - slider.cpp - Reagiert jetzt besser auf Wertänderungen - i18n.cpp - neue Texte für HSVRGB 12.02.00 12:26 - smooth alpha 0.6.6.1 - popupmenu.cpp - Fehler behoben 12.02.00 12:12 - smooth alpha 0.6.6.0 - window.cpp - Fehler behoben - colordlg.cpp - Erweiterungen 11.02.00 17:55 - smooth alpha 0.6.5.0 - colordlg.cpp - Erweiterungen am Dialog - neue Library libpicture hinzugefügt - neue Toolkit Version mit Inline Funktionen 10.02.00 19:42 - smooth alpha 0.6.4.0 - color.cpp - neue Datei - enthält Funktionen zur Farbkonvertierung - dialogs.cpp - neue Datei - Aufrufe für Standarddialoge - colordlg.cpp - Dialog zur Farbauswahl - editbox.cpp - Anpassungen an neue mpString Version - i18n.cpp - Strings für Farbauswahldialog hinzugefügt - char * durch string ersetzt - Toolkit upgedatet - mpString auf Version 0.2.4.0 upgedatet 09.02.00 14:39 - smooth alpha 0.6.3.1 - scrollbar.cpp - Verbesserungen bei vertikalen Scrollbars 09.02.00 14:18 - smooth alpha 0.6.3.0 - tree.cpp - Standardklasse für TreeViews - treeentry.cpp - Klasse für Einträge in einem TreeView 08.02.00 11:19 - smooth alpha 0.6.2.0 - scrollbar.cpp - SMOOTHSlider Code in SMOOTHScrollbar integriert 07.02.00 18:43 - smooth alpha 0.6.1.0 - definitions.cpp - xx_HORZ und xx_VERT Konstanten durch OR_HORZ und OR_VERT ersetzt - layer.cpp - Akzeptiert jetzt Scrollbar Objekte - scrollbar.cpp - Jetzt vollständig implementiert - neue Toolkit Version, die jetzt '&' Zeichen erkennt (wichtig für Menüeinträge) - mpString auf Version 0.2.3.0 upgedatet - Versionsnummer auf 0.6 erhöht 07.02.00 11:27 - smooth alpha 0.5.12.0 - scollbar.cpp - neues Objekt - eine Scrollbar, die schon lange gefehlt hat - slider.cpp - lässt sich jetzt durch einfachen Klick auf den Sliderbereich verschieben 06.02.00 14:12 - smooth alpha 0.5.11.2 - editbox.cpp - einige Fehler im Verhalten behoben; jetzt vollständig, bis auf Markierungen 06.02.00 12:14 - smooth alpha 0.5.11.1 - editbox.cpp - Änderungen im Verhalten - allerdings immernoch sehr fehlerhaft 06.02.00 11:40 - smooth alpha 0.5.11.0 - window.cpp - neue Funktionen, um das Icon festzulegen; erlaubt es eine Iconresource zu laden 05.02.00 17:41 - smooth alpha 0.5.10.4 - editbox.cpp - Viele Änderungen im Verhalten 05.02.00 16:35 - smooth alpha 0.5.10.3 - stk.cpp - ist jetzt long long kompatibel - container.cpp - Fehler in RequestObject behoben 05.02.00 12:06 - smooth alpha 0.5.10.2 - text.cpp - Fehler im Konstruktor behoben - application.cpp - Fehler in UnregisterObject behoben - stk.cpp - neue Funktion GetSMOOTHApplication() - window.cpp - PeekProc und MessageProc wird nicht mehr ausgeführt, wenn ein PopupMenu aktiv ist - version.rc - Änderungen bei der Speicherung der Versionsnummer - alle Objekte deregistrieren sich jetzt selbst, falls der Programmierer das nicht tut 05.02.00 11:27 - smooth alpha 0.5.10.1 - editbox.cpp - Fehler behoben, der das erste Zeichen verschluckte - mpString auf Version 0.2.2.0 aktualisiert 05.02.00 11:07 - smooth alpha 0.5.10.0 - arrows.cpp - Fehler behoben - Abstürze unter Windows 9x behoben 04.02.00 22:05 - smooth alpha 0.5.9.1 - editbox.cpp - Fehler beim Umgang mit Strings behoben - layer.cpp - Importierungsfehler behoben - object.cpp - Importierungsfehler behoben 04.02.00 18:03 - smooth alpha 0.5.9.0 - button.cpp - Anpassungen an string Klasse - editbox.cpp - neue Funktion GetText(); - object.cpp - Handles sind jetzt long long - text ist jetzt string - container.cpp - Anpassungen an long long Handles - resources.rc - neue Datei - hält alle Resourcen zusammen - editbox.cpp enthält einen Fehler, der dafür sorgt, dass das erste Zeichen, wenn es weggescrollt wird 'vergessen' wird 03.02.00 20:42 - smooth alpha 0.5.8.0 - editbox.cpp - benutzt jetzt string statt char *; dadurch konnten einige Fehler behoben werden - neue Bibliothek mpString hinzugefügt 02.02.00 16:13 - smooth alpha 0.5.7.0 - editbox.cpp - text wird jetzt nicht mehr gelöscht, sondern auf NULL gesetzt - IOLib auf Version 2.0 upgedatet 23.01.00 19:40 - smooth alpha 0.5.6.0 - editbox.cpp - Änderungen im Verhalten, die allerdings noch nicht richtig funktionieren - mpTrace auf Version 0.5.2 aktualisiert - smooth stürzt u.U. unter Windows 9x ab. Läuft unter Windows 2000 (Beta 3) stabil 16.01.00 20:43 - smooth alpha 0.5.5.2 - zusätzliche Objekte einer smooth Anwendung müssen jetzt smoothx.h aufnehmen (nicht smooth.h) 16.01.00 20:29 - smooth alpha 0.5.5.1 - definitions.cpp - Weitere Konstanten werden jetzt exportiert - menu.cpp - NULLMENU wird jetzt exportiert 16.01.00 20:16 - smooth alpha 0.5.5.0 - definitions.cpp - NULLPROC wird jetzt exportiert 15.01.00 11:06 - smooth alpha 0.5.4.0 - editbox.cpp - Message Handling verbessert - Defaultgröße gesetzt 14.01.00 20:46 - smooth alpha 0.5.3.0 - editbox.cpp - Alle gefundenen Fehler behoben 13.01.00 19:11 - smooth alpha 0.5.2.1 - Sprachunterstützung verbessert (39 weitere Sprachen hinzugefügt) 13.01.00 14:45 - smooth alpha 0.5.2.0 - Viele Fehler aus der letzten Version behoben - Änderungen an den meisten Dateien 12.01.00 20:36 - smooth alpha 0.5.1.2 - menubar.cpp - Fehler bei der Abarbeitung der WM_LBUTTONUP Message behoben - iconbar.cpp - Fehler bei der Abarbeitung der WM_LBUTTONUP Message behoben - Neues Beispielprogramm: BeatClock 12.01.00 16:43 - smooth alpha 0.5.1.1 - Neues Beispielprogramm: TestKey 12.01.00 15:50 - smooth alpha 0.5.1.0 - layer.cpp - Variable visible wird jetzt initialisiert - Anpassungen in Hide() - register.cpp - erbt jetzt von SMOOTHContainer - Layer müssen jetzt registriert werden - Anpassungen an neue Verwaltung - i18n.cpp - Neuer String "TXT_ERROR_STRINGTYPE" - TXT_OBJECTMANAGEREXISTS in TXT_ERROR_OBJECTMANAGEREXISTS umbenannt - titlebar.cpp - Fehler bei der Bearbeitung der WM_MOUSEMOVE Message behoben - Fehler aus Version 0.3.3.4 behoben, scheint jetzt stabil zu laufen - Versionsnummer auf 0.5 erhöht, da die Kriterien dafür jetzt erfüllt sind 11.01.00 19:31 - smooth alpha 0.3.3.4 - register.cpp - Neues Objekt SMOOTHRegister - slider.cpp - Neues Objekt SMOOTHSlider - editbox.cpp - Neues Objekt SMOOTHEditBox - arrows.cpp - Neues Objekt SMOOTHArrows - layer.cpp - Akzeptiert jetzt neue Objekte - Diese Version ist nicht getestet und wahrscheinlich sehr fehlerhaft! 11.01.00 17:41 - smooth alpha 0.3.3.3 - activearea.cpp - Defaultgröße definiert 11.01.00 17:28 - smooth alpha 0.3.3.2 - winapp.cpp - Cursor IDC_LINKHAND wird jetzt korrekt geladen - activearea.cpp - Neues Objekt SMOOTHActiveArea - bitmap.cpp - Neues Objekt SMOOTHBitmap - divisionbar.cpp - Neues Objekt SMOOTHLayerDivisionbar - hyperlink.cpp - Neues Objekt SMOOTHHyperlink - layer.cpp - Akzeptiert jetzt neue Objekte 11.01.00 11:24 - smooth alpha 0.3.3.1 - groupbox.cpp - Neues Objekt SMOOTHGroupBox - text.cpp - Neues Objekt SMOOTHText - layer.cpp - Akzeptiert jetzt neue Objekte - window.cpp - Weitere Anpassungen an neue Objektstruktur 11.01.00 09:17 - smooth alpha 0.3.3.0 - layer.cpp - Nach Bearbeiten einer Message wird die Abarbeitung jetzt abgebrochen - button.cpp - Process() gibt jetzt Status zurück - checkbox.cpp - Process() gibt jetzt Status zurück - optionbox.cpp - Process() gibt jetzt Status zurück 10.01.00 21:54 - smooth alpha 0.3.2.2 - button.cpp - WM_MOUSEMOVE wird jetzt direkt übergeben 10.01.00 21:46 - smooth alpha 0.3.2.1 - checkbox.cpp - Verbesserung der Reaktion auf Messages - optionbox.cpp - Verbesserung der Reaktion auf Messages - Objektverwaltungssystem überarbeitet - Anpassungen an fast allen Header- und Programmdateien 10.01.00 15:09 - smooth alpha 0.3.2.0 - messagebox.cpp - Verallgemeinerung der SMOOTHButton Benutzung 09.01.00 20:27 - smooth alpha 0.3.1.6 - checkbox.cpp - neues Objekt SMOOTHCheckbox - optionbox.cpp - neues Objekt SMOOTHOptionbox - layer.cpp - Anpassungen an neue Objekte - window.cpp - Anpassungen an neue Objekte - popupmenu.cpp - Anpassungen an neue Objekte 09.01.00 17:56 - smooth alpha 0.3.1.5 - window.cpp - benutzt jetzt destroyed Variable, um festzustellen, ob Fenster schon zerstört wurde 09.01.00 17:35 - smooth alpha 0.3.1.4 - messagebox.cpp - MessageBoxen reimplementiert - window.cpp - Stay() Funktion wieder verfügbar - stk.cpp - Anpassungen an MessageBoxen 09.01.00 15:19 - smooth alpha 0.3.1.3 - button.cpp - Fehler behoben, der dazu führte, dass sich keine Button Objekte anzeigen ließen - layer.cpp - Fehler behoben, der das Registrieren eines Buttons verhinderte 09.01.00 14:56 - smooth alpha 0.3.1.2 - button.cpp - neues Objekt SMOOTHButton - layer.cpp - Anpassungen an SMOOTHButton - window.cpp - Anpassungen an SMOOTHButton - stk.cpp - Anpassungen an SMOOTHLayer 09.01.00 14:15 - smooth alpha 0.3.1.1 - RecArray auf Version 0.9.2.0 upgedatet 09.01.00 13:49 - smooth alpha 0.3.1.0 - layer.cpp - Objekt SMOOTHLayer hinzugefügt - stk.cpp - Funktion LoadSMOOTHBitmap hinzugefügt - i18n.cpp - Neuer String TXT_LAYER - Versionsnummer auf 0.3 erhöht, da Kriterien für diese Version jetzt erfüllt sind 09.01.00 11:17 - smooth alpha 0.1.8.0 - Fehler an Headerdateien behoben - RecArray auf Version 0.9.1.2 aktualisiert 07.01.00 20:23 - smooth alpha 0.1.7.3 - divisionbar.cpp - Neue Klasse - SMOOTHDivisionbar - window.cpp - Anpassungen an SMOOTHDivisionbar - client.cpp - Anpassungen an SMOOTHDivisionbar - einige Änderungen an Headerdateien - RecArray auf Version 0.9.1.1 upgedatet 07.01.00 18:31 - smooth alpha 0.1.7.2 - RecArray auf Version 0.9.1.0 upgedatet 07.01.00 14:26 - smooth alpha 0.1.7.1 - mpTrace auf Version 0.5.1 upgedatet 07.01.00 12:45 - smooth alpha 0.1.7.0 - version.rc - Versionsinfo kann jetzt von Windows verarbeitet werden 06.01.00 23:24 - smooth alpha 0.1.6.2 - popupmenu.cpp - Stürzt jetzt nicht mehr ab - Änderung an Activate() 06.01.00 22:58 - smooth alpha 0.1.6.1 - Neue RecArray Version: 0.8.8.0 - smooth stürzt zur Zeit ab, wenn ein PopupMenu mehrere Einträge enthält 06.01.00 18:17 - smooth alpha 0.1.6.0 - popupmenu.cpp - Neue Klasse - Verwaltet Popup Menüs - window.cpp - Anpassungen an neue SMOOTHPopupMenu Klasse - menu.cpp - Anpassungen für PopupMenu - menubar.cpp - Anpassungen für PopupMenu - iconbar.cpp - Anpassungen für PopupMenu smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2001000066400000000000000000000271441516402577000226170ustar00rootroot00000000000000ChangeLog for smooth 23.12.01 17:07 - smooth alpha 0.8.57.0 - window.cpp - Container Vereinheitlichung abgeschlossen - menubar.cpp - vertikale Menubars implementiert - Fehler behoben - primitive.cpp - Basisklasse für geometrische Primitive - point.cpp - Abstraktion von Punkten - size.cpp - Abstraktion von Breite und Höhe - rect.cpp - Abstraktion von Rechtecken - line.cpp - Abstraktion von Linien - dllmain.cpp - SMOOTHDllMain durch DllMain ersetzt (behebt Fehler) - object.cpp - Paint() Methode durch Paint(int) ersetzt - Vorbereitung für Themes - containertype.cpp - neue Klasse: Verwaltung verschiedener Container-Typen - ersetzt SMOOTHObjectInfo - hyperlink.cpp - Links verändern jetzt die Farbe, wenn mit der Maus darauf gezeigt wird - SMOOTHObjectInfo Klasse entfernt - SMOOTH* Klassen können jetzt als S* geschrieben werden - LibXML Bibliothek integriert - 'Gray' wird jetzt überall mit a geschrieben - IOLib auf Version 4.0b aktualisiert - RecArray durch SMOOTHArray ersetzt (und Update auf Version 0.10.4.0 (MSVC kompatibel)) - long long's entfernt (für MSVC Kompatibilität) - alle Object ID's werden jetzt mit SMOOTH::RequestObjectID() ermittelt - Anpassungen an vielen Objekten 24.07.01 18:15 - smooth alpha 0.8.56.0 - designer.cpp - neue Anwendung: Dialogeditor - window.cpp - SM_MOUSEMOVE Nachrichten, die von der SMOOTHBackgroundApplication kommen, werden jetzt nicht mehr an die MessageProc weitergegeben - wertet jetzt auch WM_NC* Nachrichten aus - updaterect wird jetzt korrekt gesetzt - popupmenu.cpp - Popups werden jetzt korrekt geschlossen - titlebar.cpp - die Größe von maximierten Fenstern kann jetzt nicht mehr geändert werden - drawable.cpp - Blitting Funktionen übernehmen jetzt Source und Destination Rect - activearea.cpp - SetColor ruft jetzt die eigene Paint Funktion auf (statt wnd->Paint()) - toolwnd.cpp - updaterect wird jetzt korrekt gesetzt - client.cpp - zeichnet jetzt nur noch den Bereich im Updaterect neu - mdiclient.cpp - zeichnet jetzt nur noch den Bereich im Updaterect neu - server.cpp - Anpassungen - sessionmanagement.cpp - Fehler #0014 behoben - hyperlink.cpp - objprops->size enthält jetzt die korrekte Größe - i18n.cpp - Falsche Zuordnung der chinesischen Zeichensätze behoben - Standardschrift ist jetzt "MicroSoft Sans Serif" statt "MS Sans Serif" (Unicode Schriftart) - Standardschrift für Japanisch: "MS PGothic" - Sprachunterstützung verbessert - string.cpp - Unabhängigkeit von mpstring - Unterstützung von Unicode - stk.cpp - Layer-Objekte, die außerhalb des Layers liegen, werden jetzt korrekt neugezeichnet - button.cpp - Unterstützung für Tooltips implementiert - tooltip.cpp - Neue Funktion: SetTimeout(...) - Komplett auf Unicode umgestellt - Übersetzungen angepasst - mpstring Library entfernt - Progressive Setup aktualisiert - IOLib auf Version 4.0a aktualisiert - RecArray erweitert (behebt Fehler #0013) - Anpassungen an fast allen Klassen 21.06.01 15:58 - smooth alpha 0.8.55.0 - tooltip.cpp - neue Klasse: SMOOTHTooltip - stk.cpp - neue Variablen: TooltipColor, TooltipTextColor 07.06.01 19:49 - smooth alpha 0.8.54.0 - string.cpp - neue Klasse: SMOOTHString - objecttype.cpp - neue Klasse: Abstrahiert Objekttypen - combobox.cpp - meldet sich jetzt als 'Owner' des ToolWindows an - toolwindow.cpp - gibt sich jetzt als OBJ_WINDOW kompatibel aus (über IsTypeCompatible; behebt Fehler #0017) - Dokumentation erweitert - Anpassungen an fast allen Objekten - IOLib Klassen werden von smooth jetzt als SMOOTHStream, SMOOTHInStream und SMOOTHOutStream exportiert - Progressive Setup upgedatet - IOLib und IOLib-Filters auf Version 4.0 aktualisiert 30.05.01 18:26 - smooth alpha 0.8.53.0 - window.cpp - benutzt jetzt automatisch die erste Menubar - filedlg.cpp - Verbesserungen - dirdlg.cpp - Verbesserungen - menubar.cpp - Menüs werden jetzt korrekt geschlossen - drawable.cpp - neue Klasse: SMOOTHDrawable - stk.cpp - GetApplication, GetLayer, GetWindow durch GetObject ersetzt - benutze jetzt neue MinGW32 Entwicklungsumgebung - Programme stürzen nicht mehr ab, wenn nicht alle Objekte deregistriert und gelöscht werden - IOLib auf Version 4.0-pre2 aktualisiert - Anpassungen an fast allen Objekten - Progressive Setup upgedatet - kit und include Verzeichnisse zusammengeführt 20.04.01 16:57 - smooth alpha 0.8.52.0 - menubar.cpp - Vereinfachungen - Geometrieverbesserungen - timer.cpp - führt jetzt objprops->proc aus - object.cpp - Konstante OBJ_ICONBAR entfernt - objectinfo.cpp - Anpassungen - Progressive Setup upgedatet 12.04.01 14:57 - smooth alpha 0.8.51.0 - window.cpp - Kann jetzt mehrere Menubars aufnehmen - Containerschnittstelle für OR_TOP, OR_BOTTOM, OR_CENTER und OR_FREE Objekte unifiziert - menubar.cpp - Menubar und Iconbar zusammengeführt - Anpassungen - titlebar.cpp - Anpassungen - client.cpp - Anpassungen - mdiclient.cpp - Anpassungen - Iconbar Objekt entfernt 06.04.01 15:34 - smooth alpha 0.8.50.0 - thread.cpp - Startverhalten der Threads korrigiert - Threads werden jetzt ordnungsgemäß angehalten und gelöscht - mutex.cpp - Mutex Unterstützung integriert - semaphore.cpp - Semaphoren Unterstützung integriert - listbox.cpp - neue Funktion: ModifyEntry - combobox.cpp - neue Funktion: ModifyEntry - sessionmanagement.cpp - einige Funktionen gehören jetzt zur Klasse SMOOTH - odsmanager.cpp - einige Funktionen gehören jetzt zur Klasse SMOOTH - definitions.cpp - neue smooth Messages - progressbar.cpp - IntegerToString Aufrufe durch itos ersetzt - colordlg.cpp - IntegerToString Aufrufe durch itos ersetzt - toolkit.cpp - mpToolkit ist jetzt Bestandteil der Core Bibliothek - messagebox.cpp - Messageboxen ohne Titel sind jetzt möglich - winapp.cpp - SMOOTH::Init erzeugt jetzt den mainObjectManager usw. - serverdlg.cpp - Fehler #0015 behoben - Fehler #0016 behoben - timer.cpp - neue Klasse: SMOOTHTimer - popupmenu.cpp - fast komplettes Rewrite - Anpassungen an vielen Objekten - IOLib aktualisiert 18.03.01 15:47 - smooth alpha 0.8.49.0 - thread.cpp - nach Linux portiert (ohne Pause und Continue Methoden) - kann jetzt auch Funktionen außerhalb von Funktionen verwalten - metrics.cpp - Konstanten werden jetzt nicht mehr exportiert - popupmenu.cpp - benutzt jetzt Toolkit-Funktionen zum Blitten - divisionbar.cpp - SMOOTHDivisionbar und SMOOTHLayerDivisionbar zusammengeführt - benutzt jetzt mainObjectManager um andere Divisionbars zu finden - stk.cpp - neue Klasse: SMOOTH - winapp.cpp - Farbvariablen befinden sich jetzt in der Klasse SMOOTH - window.cpp - kann jetzt mehrere Layer aufnehmen - titlebar.cpp - wird jetzt nicht mehr inaktiv, wenn eine ComboBox geöffnet wird - filedlg.cpp - Layout verändert - messagebox.cpp - Führt unter Windows jetzt ein MessageBeep aus - Anpassungen in fast allen Dateien - Copyright Informationen aktualisiert - mpToolkit erweitert - Progressive Setup aktualisiert 18.02.01 17:32 - smooth alpha 0.8.48.1 - optionbox.cpp - wird jetzt sichtbar deaktiviert - Lizenz angepasst - BeatClock Version 2.0 fertiggestellt 18.02.01 15:56 - smooth alpha 0.8.48.0 - window.cpp - Verbesserungen an RegisterObject und UnregisterObject - popupmenu.cpp - Fehler behoben, der dazu führte, dass nur ein Popup Menü gleichzeitig geöffnet werden konnte - divisionbar.cpp - SMOOTHDivisionbar benutzt jetzt nicht mehr SMOOTHWindow::divisionbars - SMOOTHLayerDivisionbar benutzt jetzt nicht mehr SMOOTHLayer::assocObjects - client.cpp - benutzt jetzt nicht mehr SMOOTHWindow::divisionbars - mdiclient.cpp - benutzt jetzt nicht mehr SMOOTHWindow::divisionbars - layer.cpp - SMOOTHLayerDivisionbar ist kein friend mehr - Verbesserungen der BeatClock - LibPCI unterstützt jetzt BZIP2 Komprimierung 13.02.01 17:56 - smooth alpha 0.8.47.0 - arrows.cpp - SetTimer wird jetzt nicht mehr bei jedem Klick aufgerufen - scrollbar.cpp - SetTimer wird jetzt nicht mehr bei jedem Klick aufgerufen - definitions.cpp - neue Konstante: SMOOTHBreak - editbox.cpp - neuer Stil: EDB_ASTERISK - Anpassungen an vielen Objekten - mpString Bibliothek aktualisiert 12.02.01 18:13 - smooth alpha 0.8.46.1 - Die Farbe RGB(192, 192, 192) wird jetzt automatisch zur Hintergrundfarbe 12.02.01 17:10 - smooth alpha 0.8.46.0 - editbox.cpp - Erweiterungen - Fehler am Server behoben - Anpassungen an vielen Objekten - Progressive Setup aktualisiert - RecArray auf Version 0.10.2.0 upgedatet 08.02.01 20:21 - smooth alpha 0.8.45.0 - layer.cpp - Paint() ruft sich jetzt selbst wieder auf, falls es unterbrochen wird - definitions.cpp - neue Message: SM_MOUSELEAVE - window.cpp - Anpassungen - titlebar.cpp - Loop benutzt jetzt standardmäßig GetMessage() statt PeekMessage() - scrollbar.cpp - Process() unterbricht jetzt nicht mehr die Message Bearbeitung bei WM_MOUSEMOVE - Anpassungen an vielen Objekten - IOLib upgedatet 07.02.01 20:53 - smooth alpha 0.8.44.0 - background.cpp - Fehler behoben - titlebar.cpp - Sendet jetzt SM_LOOSEFOCUS Message, wenn Fenster verschoben werden soll - hyperlink.cpp - Verbesserungen - editbox.cpp - Erweiterungen - window.cpp - Fehler bei der Cursorbehandlung behoben - RecArray auf Version 0.10.1.0 aktualisiert 06.02.01 20:14 - smooth alpha 0.8.43.0 - background.cpp - neue Klasse: Sendet im Hintergrund WM_MOUSEMOVE Messages in regelmäßigen Abständen an alle Fenster - dllmain.cpp - Instantiiert jetzt SMOOTHBackgroundApplication - winapp.cpp - Anpassungen - window.cpp - Definition von NULLWND entfernt 04.02.01 19:04 - smooth alpha 0.8.42.0 - editbox.cpp - Verbesserungen - winapp.cpp - SMOOTHLoop() aufgeräumt - thread.cpp - Threads werden jetzt erst gestartet, wenn ein Loop aktiv ist 01.02.01 20:35 - smooth alpha 0.8.41.1 - stk.cpp - Anpassungen - Verbesserungen an LibPCI - komplett auf PCIFF umgestellt 01.02.01 15:31 - smooth alpha 0.8.41.0 - stk.cpp - benutzt jetzt IOLib statt Windows Funktionen - LibPCI integriert 31.01.01 20:16 - smooth alpha 0.8.40.0 - IOLib auf Version 4.0-pre1 aktualisiert - Progressive Setup aktualisiert 11.01.01 19:18 - smooth alpha 0.8.39.0 - layer.cpp - Fehler in Hide() behoben - stk.cpp - neue Funktion: RequestGUID() ermittelt einen eindeutiges Handle - editbox.cpp - kleinere Verbesserungen - Anpassungen am Server - Befehl getGUID implementiert - Objekte an neues GUID System angepasst 06.01.01 19:54 - smooth alpha 0.8.38.0 - combobox.cpp - Fehler behoben - container.cpp - prüft jetzt, ob Objekte NULL sind - application.cpp - prüft jetzt, ob Objekte NULL sind - layer.cpp - prüft jetzt, ob Objekte NULL sind - window.cpp - prüft jetzt, ob Objekte NULL sind - register.cpp - prüft jetzt, ob Objekte NULL sind - object.cpp - zwei neue Funktionen: SetToolTip() und GetToolTip() (bisher aber nicht von Objekten implementiert) 04.01.01 20:03 - smooth alpha 0.8.37.0 - editbox.cpp - Fehler in SetText() behoben - combobox.cpp - Fehler behoben - Verbesserungen am Server 03.01.01 21:55 - smooth alpha 0.8.36.1 - combobox.cpp - Font kann jetzt verändert werden - geometrische Verbesserungen - listbox.cpp - Font kann jetzt verändert werden - Fehler behoben 03.01.01 18:22 - smooth alpha 0.8.36.0 - list.cpp - SelectEntry() in SelectListEntry() umbenannt - Cleanup() in CleanupList() umbenannt - combobox.cpp - neue Funktionen: SelectEntry() und Cleanup() - AddEntry() und RemoveEntry() rufen jetzt Paint() auf - listbox.cpp - neue Funktionen: SelectEntry() und Cleanup() - AddEntry() und RemoveEntry() rufen jetzt Paint() auf - Progressive Setup upgedatet - Versionsinfo aktualisiert smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2002000066400000000000000000000101541516402577000226110ustar00rootroot00000000000000ChangeLog for smooth 16.11.02 18:51 - smooth alpha 0.8.60.0 - listbox.cpp - now uses the SMOOTHSurface interface - implemented Show() and Hide() functions - improved entry adding - improved speed - new function: AllowReselect(SMOOTHBool) - scrollbar.cpp - added mouse wheel support - added support for the VK_PRIOR and VK_NEXT keycodes for mouse wheel replacement on some notebooks - editbox.cpp - improved IME support - string.cpp - new function: ConvertTo(char *encoding) - new function: CompareN(const SMOOTHString &, int); - document.cpp - fixes in SaveFile - new function: SetEncoding(SMOOTHString) - upgraded to bzip2 v1.0.2 - upgraded to IOLib v4.9.13.0 - upgraded to iconv v1.8 - new translator application to create and edit xml language files 20.09.02 23:21 - smooth alpha 0.8.59.0 - groupbox.cpp - fixed Hide() function - parser.cpp - removed class SMOOTHXMLParser (XML parser is still present, but integrated into SMOOTHXMLDocument) - upgraded to IOLib v4.9.8.0 - fixed some minor bugs 18.08.02 12:15 - smooth alpha 0.8.58.1 - objectmanager.cpp - fixed a bug that could lead to an infinite loop when leaving a smooth application - popupview.cpp - fixed a bug that could lead to crashes - editbox.cpp - now uses WM_CHAR messages to get character codes - implemented a new standard dialogs api - smooth uses windows dialogs now 28.06.02 16:06 - smooth alpha 0.8.58.0 - titlebar.cpp - fixed some minor bugs (maximizing) - editbox.cpp - EditBoxes with EDB_NUMERIC style accept decimal numbers now - drag.cpp - new class: SMOOTHDragControl; allows easy moving of windows - layer.cpp - added support for colored layers - allowed SetMetrics for layers - date.cpp - new class: SMOOTHDate - time.cpp - new class: SMOOTHTime - object.cpp - removed containerindex variable and replaced it with myContainer - added GetRealPosition from stk.cpp - a bit of 'code beautifying' - new functions EnterProtectedRegion and LeaveProtectedRegion - popupmenu.cpp - splitted to PopupMenu and PopupView - complete reimplementation - many bugfixes (fixes bug #0018) - popupview.cpp - new class: viewing of popup menus - string.cpp - ImportMBCS uses libiconv now - replaced SIF_ANSI with SIF_ISO (ISO-8859-1) - hyperlink.cpp - great increase in API compatibility - menu.cpp - replaced SMOOTHMenuEntry with Entry - restructured Entry - entries can now have a description that is displayed in the statusbar - tree.cpp - replaced SMOOTHTreeEntry with Entry - list.cpp - replaced SMOOTHListEntry with Entry - document.cpp - new class: SMOOTHXMLDocument - node.cpp - new class: SMOOTHXMLNode - attribute.cpp - new class: SMOOTHXMLAttribute - window.cpp - new function: SetStatusText - changes the text of the statusbar (if it exists) - new function: SetMinimumSize - background.cpp - implemented a method for save deletion of objects - stk.cpp - new function: DeleteObject(SMOOTHObject *) - surface.cpp - metaclass for surfaces (currently only Windows GDI) - surfacegdi.cpp - surface implementation for Windows GDI - thread.cpp - Pause() and Continue() are no longer supported - removed session management and ODS functionality (will be readded later) - SMOOTH now uses LiSAThreads on all systems - removed SMOOTHDrawable class - renamed SMOOTHRegister to SMOOTHTabRegister - allowed compilation without Unicode support - added a test for the 'Microsoft Sans Serif' font - many bugfixes, unifications and 'code beautifying' - added basic smooth types (SMOOTH* {Bool, Byte, Float, Int, Short, Void}) - replaced RECT, POINT and SIZE variables by SMOOTHRect, SMOOTHPoint and SMOOTHSize - updated Copyright information - updated Progressive Setup - fixed errors in RecArray - updated IOLib to version 4.9.6.0 - updated libxml2 to version 2.4.13 - integrated libiconv v1.7 - integrated LiSA - many restructurings - started the QNX port - finished the MSVC port - smooth is now spelled with lower case letters - replaced the roadmap with a more extensive ToDo list - changed to english as the only language in ChangeLog, ToDo, Buglist, etc smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2003000066400000000000000000000144311516402577000226140ustar00rootroot00000000000000ChangeLog for smooth 28.12.03 23:45 - smooth alpha 0.8.63.0 - string.cpp - new method: Replace(const String &, const String &); search for the first string and replace with the second - new method: ComputeCRC32(); get the CRC32 hash sum of the string - i18n.cpp - new class: Translator; implements the i18n system known from BonkEnc - extended.cpp - new template: provides support for data driven code execution (Extended Data Types, EDT) - image.cpp - renamed class Bitmap to Image - bitmap.cpp - new class: Bitmap; abstraction of bitmap objects in memory - bitmapgdi.cpp - new class: BitmapGDI; Bitmap implementation for Windows GDI surfaces - modified many APIs to use GUI::Bitmap instead of HBITMAP - removed obsolete friend declarations - changed classes directory layout - added support for right-to-left scripts like Arabic or Hebrew - improved stability on Windows 9x/ME - upgraded to libxml v2.5.10 - removed libpicture - separated iconv from smooth - it is now only required for using non-latin scripts - smaller improvements - some bufixes - license changed to 'The Artistic License, Version 2.0' 03.07.03 17:13 - smooth alpha 0.8.62.0 - string.cpp - renamed IntToString to FromInt, DoubleToString to FromFloat - renamed ToDouble to ToFloat - new method: SetOutputFormat(const char *); - string only uses unicode internally now - default input format is now ISO-8859-1 again - String no longer hangs when input doesn't match input format - buffers returned from ConvertTo or SetInputFormat are now deleted regularly - window.cpp - Paint() now uses SP_UPDATE - added new callback: Menu *getTrackMenu(Int mouseX, Int mouseY) - fixed issues with modal and topmost windows - removed SM_MOUSELEAVE message (functionality is now integrated in Window::IsMouseOn(...)) - new signal: onResize(Void) - surface.cpp - modified StartPaint and EndPaint methods - added PaintRect method: updates the requested region - pciio.cpp - read-only files can now be opened - button.cpp - new method: SetBackgroundColor(Int) - a double-click is now handled as two single clicks - widget.cpp - new method: SetFlags(Int), allows to set generic flags for widgets - onClick now takes two parameters, the x and y position of the mouse pointer - listbox.cpp - support for hiding the scrollbar and header - added methods to remote control scrolling - added an LF_MULTICHECKBOX flag; support for selecting multiple entries - array.cpp - improved speed of GetNthEntry() - renamed DeleteEntry to RemoveEntry, DeleteAll to RemoveAll - fixed a bug that crashed Array when an entry was inserted in a previously cleaned array - list.cpp - class List now inherits from class Array - new method: SetReferenceList(List *), lets the list stay synchronized with the reference - renamed Cleanup() to RemoveAll() - signaln.cpp - slots can now be disconnected from signals - slots taking zero parameters can now be connected to any signal - SetParentObject can be used to specify an object that will automatically be protected on Signal::Emit - titlebar.cpp - hide min/max buttons if both are inactive - editbox.cpp - added support for dropdown lists with default strings - font.cpp - new class: abstraction of font metrics - fontdlg.cpp - implemented a font selection dialog - background.cpp - messages are now sent to all threads; fixes some problems with multithreaded applications - document.cpp - added support for parsing XML documents in memory - popupview.cpp - popups now open automatically when the mouse is moved on a popup entry - menubar.cpp - iconbars now support bigger icons - shortcut.cpp - new class: provides support for keyboard shortcuts - fixed programs slow down when running for a longer time - UnregisterObject() is no longer required unless you are removing an Object before the program quits - introduced a new font management system - fixed some PopupMenu issues - upgraded to IOLib v4.9.14.0 - added support for Windows 95 - many bugfixes 16.03.03 07:00 - smooth alpha 0.8.61.0 - math.cpp - new class: contains static mathematical functions - binary.cpp - new class: contains static binary helper functions - replaces old binary helper functions - datetime.cpp - new class: merges old SMOOTHDate and SMOOTHTime classes - divider.cpp - renamed old SMOOTHDivisionbar class - tabwidget.cpp - renamed old SMOOTHTabRegister class - pciio.cpp - integrated LibPCI into the main library (will be replaced by a new API later) - window.cpp - Windows now create a Layer automatically, so you can register Layer objects at a Window object - new method: Close() - new method: IsMouseOn(Rect) - new methods: MouseX(), MouseY() - new methods: Maximize(), Restore() - new method: SetMaximumSize(Size) - stk.cpp - removed function CloseWindow(Window *) - removed class Setup - colordlg.cpp - color box now updates when the vertical hue selector is moved - system.cpp - new class: includes basic functionality like GUIDs - array.cpp - implemented static GetNthEntry method - widget.cpp - new class: base class for GUI objects - setup.cpp - new class: replaces old SMOOTH::Setup - object.cpp - moved many methods to class GUI::Widget - timer.cpp - Timers no longer need to be registered and are now independent of Windows - surface.cpp - new method: Gradient(...), replaces same function in toolkit.cpp - input.cpp - new class: contains mouse and keyboard input functionality - droparea.cpp - new class: receiver for drag & drop files - button.cpp - new methods: SetFlags(Int), GetFlags(), flags: BF_NORMAL, BF_NOFRAME - editbox.cpp - support for 'Home' and 'End' keys - support for marking text - support for copy and paste to/from clipboard - fixed other editbox issues - new namespace: smooth alias S - new namespace: smooth::XML - new namespace: smooth::GUI - ported the whole library to the new smooth namespace layout - added the pcitools (ras2pci and pci2ras) - TestKey now displays Unicode character codes - replaced the 'Procs' by a new template based callback mechanism - added support for signals and slots - Threads, Semaphores and Mutexecs no longer need to be registered - upgraded libxml to version 2.5.1 - fixed the flickering when resizing a window smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2004000077500000000000000000000067431516402577000226270ustar00rootroot00000000000000ChangeLog for smooth 18.11.04 00:06 - smooth alpha 0.8.65.0 - editbox.cpp - improved multiline editbox - renderer.cpp - started implementation of an XUL renderer - window.cpp - windows can now be shown minimized initially - array.cpp - improved smooth::Array implementation - file.cpp - new class: File; basic file handling routines - directory.cpp - new class: Directory; basic directory handling routines - signal.cpp - improved signals and slots implementation - extended.cpp - improved Extended<> class - implemented -> and * operators - math.cpp - implemented integer versions of Abs, Pow, Min, Max and Mod - form.cpp - class Primitive renamed to Form - container.cpp - moved into namespace GUI - containers now inherit from Widget - added auto registration for backends (just compile and link any new backends to use them; no need to change existing code) - added the fribidi library to support RTL scripts on all systems - improved smooth Translator utility - removed large fonts support; it will be reimplemented later - added an SDL threads backend - added XLib backends for Bitmaps and Surfaces - added an IOLib driver for accessing files with Unicode filenames 11.03.04 15:42 - smooth alpha 0.8.64.0 - rect.cpp - new methods: Bool DoRectsOverlap(Rect, Rect); and Rect OverlapRect(Rect, Rect); - widget.cpp - new method: Bool IsAffected(Rect &); replaces corresponding STK function - window.cpp - splitted into Frontend and Backend parts - fixed crashes on Windows 9x - windowgdi.cpp - new class: WindowGDI; implements Window API for Win32 systems - bitmap.cpp - splitted into a frontend and a system dependent backend part - surface.cpp - splitted into a frontend and a system dependent backend part - made thread safe - messagebox.cpp - S::SMOOTH::MessageBox is now S::QuickMessage - renamed MessageBoxApp to MessageDlg - MessageDlg can now show a CheckBox with a message - callbackn.cpp - You can now connect values directly to the Callback, the connected value will be returned without any function being called - config.cpp - new class: Configuration; an interface to XML configuration files - tipodaydlg.cpp - new dialog: 'Tip of the Day' dialog window - menuentry.cpp - started redesign of the menu system - MenuEntry is now a Widget - mutex.cpp - splitted into frontend and backend parts - semaphore.cpp - splitted into frontend and backend parts - thread.cpp - splitted into frontend and backend parts - revised and improved Thread API - timer.cpp - splitted into frontend and backend parts - wrote SDL backend for Timers - string.cpp - removed IsUTF8() method as this is handled automatically by ConvertString(...) - new method IsUnicode() - array.cpp - fixed a stack overflow (recursion) in RemoveAll() if an Array has too many entries - editbox.cpp - added signal: onEnter; emitted when the user finishes input with enter/return - event.cpp - new class: implements system events - loop.cpp - generalized event handling - new namespace GUI::Dialogs contains all dialogs plus MessageBox (now MessageDlg) and SplashScreen - new namespace Threads contains everything related to multi threading - new namespace System contains classes System and Timer - removed ThreadManager - removed some Windows API calls - removed smooth Toolkit (STK, stk.cpp) - removed mpToolkit (toolkit.cpp) - removed threads support from LiSA - switched to an XML ToDo list system - add DTDs for ConfigFile and LangFile XML file types - many smaller bugfixes and improvements - fixed Makefile.static smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2005000077500000000000000000000014001516402577000226110ustar00rootroot00000000000000ChangeLog for smooth 09.01.05 14:00 - smooth alpha 0.8.66.0 - object.cpp - incorporated object manager functionality into Object - window.cpp - fixed a possible crash on window close - widget.cpp - added attributes from former ObjectProperties - only widgets can be registered at container objects now - xulloader.cpp - added a XUL loader that can be executed via rundll32 - button.cpp - new class: XUL::Button - label.cpp - new class: XUL::Label - description.cpp - new class: XUL::Description - args.cpp - new class: ArgumentsParser; parser for command line arguments - listentry.cpp - added support for tooltips - tooltip.cpp - added support for multi line text - removed ObjectManager - removed ObjectProperties - upgrade to libXML2 version 2.6.16 smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2006000077500000000000000000000062071516402577000226240ustar00rootroot00000000000000ChangeLog for smooth 22.12.06 16:04 - smooth alpha 0.8.69.0 - bitmap.cpp - Added a method for inverting the colors of a bitmap - popupmenu.cpp - Added support for images in popup menu entries - slider.cpp - Added support for changing the slider grip size - added multi monitor support - made compatible with big window frames - fixed nonblocking function calls support - lots of bug fixes 18.06.06 15:10 - smooth aplha 0.8.68.0 - shortcut.cpp - Added support for menu shortcuts - buffer.cpp - Added Base 64 encoder and decoder - memory.cpp - New class for memory management to prevent bad memory frees using Buffer - driver_https.cpp - Added an IO driver for HTTPS proxy connections - some smaller bug fixes 29.03.06 13:23 - smooth alpha 0.8.67.0 - listentry.cpp - ListEntries are now Widgets - list.cpp - List now derives from Container - changed the way entries are handled - dirdlg.cpp - allow to set the initially selected directory with SetDirName - the new style directory selection dialog is used if available - error.cpp - added error classes - object.cpp - new function: ToString() - widget.cpp - all widgets can have tooltips now - implemented a universal Process(...) method to replace most others - surface.cpp - fixed frames being painted too large - editbox.cpp - fixed copying text to clipboard (now using GlobalAlloc instead of new) - allowed copying from inactive editboxes - checkbox.cpp - replaced SM_CHECKCHECKBOXES with a static signal - optionbox.cpp - replaced SM_CHECKOPTIONBOXES with a static signal - textbox.cpp - new class: XUL::TextBox - box.cpp - new class: XUL::Box; implements , and - groupbox.cpp - GroupBoxes are now Layers - editbox.cpp - removed multi line support - now using Cursor widget - multiedit.cpp - new class: MultiEdit; implements a multi line edit box - console.cpp - new class: System::Console; implements a simple console API - string.cpp - added method: Find(String); returns the position of the given string (or -1) - added methods: ToLower(), ToUpper() - added native support for UTF-16BE encoding - simplified iconv usage (with great speedups) - color.cpp - new class: Color; replaces old color.cpp - array.cpp - some optimizations to increase speed - code cleaned up - dynamicloader.cpp - new class: DynamicLoader; dynamic module loader - hotspot.cpp - new class: Hotspot; simple widget to handle user action - scrollbar.cpp - improved scrolling with mouse wheel - added a class for smart pointers - added a class for nonblocking function calls - removed useless tree widget implementation (will be replaced by a new one later) - improved XUL support - simplified XML API - replaced "smooth Test" with a more serious test application - replaced IOLib with a native smooth IO interface - replaced the old Container system with a new "every widget is a container" system - cleaned most code, reduced codesize (source and binary) - removed shlobjmini.h - removed support for MinGW 1.x - replaced fribidi with fribidi2 - upgrade to libXML2 version 2.6.22 - moved to the xmlTextReader and xmlTextWriter APIs of libxml - now using precompiled headers in the build process smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2007000077500000000000000000000011141516402577000226150ustar00rootroot00000000000000ChangeLog for smooth 21.02.07 16:41 - smooth alpha 0.8.69.2 - windowgdi.cpp - Windows can now be minimized using the task bar button - some bug fixes 06.02.07 13:18 - smooth alpha 0.8.69.1 - list.cpp - Speed optimizations - buffer.cpp - Fixed problems when using const Buffer<> - icon.cpp - Added an image loader for Windows icon resources - widget.cpp - Renamed RegisterObject to Add - Renamed UnregisterObject to Remove - application.cpp - Moved main loop to Application - simplified Array<> API - converted project to MSVC 8.0 - lots of fixes for non latin Windows 9x/ME smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2008000077500000000000000000000037141516402577000226260ustar00rootroot00000000000000ChangeLog for smooth 22.03.08 11:25 - smooth alpha 0.8.70.0 - string.cpp - fixed string conversion when inEncoding == outEncoding - new function: Trim, strips whitespaces from both ends of a string - config.cpp - configuration is no longer automatically saved - widget.cpp - added a universal context menu framework - tooltips are no longer displayed if the containing window is inactive - window.cpp - removed support for context menus - removed signal onResize (using Widget::onChangeSize instead) - fixed display of a black window when part of it is outside the working area - system.cpp - new function: GetAPIVersion() - new functions to retrieve system folder locations - listentry.cpp - ListEntries can now be displayed inactive - protocol.cpp - new class: Protocol, base class for network protocol implementation - file.cpp - new class: File, implementation of the file:// protocol - http.cpp - new class: HTTP, HTTP protocol implementation - scrollbar.cpp - changed scrollbar behaviour to be more Windows-like - surfacecairo.cpp - added support for Cairo surfaces - semaphore.cpp - added support for initializing semaphores with a maximum value - rwlock.cpp - new class: RWLock, implements a simple read/write lock based on Mutex and Semaphore - md5.cpp - new class: MD5, implements the message digest algorithm - number.cpp - new class: Number, implements string to number conversions - treeview.cpp - new class: TreeView, container for Tree entries - tree.cpp - new class: Tree, implements Tree entries for Lists - completely new and improved Array implementation - new template class: Iterator, iterator for arrays of type Array - added missing operator =() to signal classes - applications now check the smooth API version instead of the release number for compatibility - added support for network files and directories - fixed grayscaled icons display in iconbars - added foreach macro - improved Linux support - improved Winelib support smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2009000066400000000000000000000000251516402577000226140ustar00rootroot00000000000000ChangeLog for smooth smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2010000066400000000000000000000000251516402577000226040ustar00rootroot00000000000000ChangeLog for smooth smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2011000066400000000000000000000000251516402577000226050ustar00rootroot00000000000000ChangeLog for smooth smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2012000066400000000000000000000000251516402577000226060ustar00rootroot00000000000000ChangeLog for smooth smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2013000066400000000000000000000067001516402577000226150ustar00rootroot00000000000000ChangeLog for smooth 15.06.13 14:48 - smooth alpha 0.8.71.0 - window.cpp - renamed doQuit to doClose - removed onPeek - removed support for the WF_SYSTEMMODAL and WF_APPTOPMOST flags - listbox.cpp - show partially visible entries again - listentry.cpp - entries in a subordinate list now respect the outer lists columns - combobox.cpp - improved drop-down list size adjustment - number.cpp - fixed floating point number -> string conversion - fixed integer -> string conversion - pointer.cpp - new class: Pointer, replaces class Input and parts of LiSA library - keyboard.cpp - new class: Keyboard, represents keyboard state - widget.cpp - new function: GetVisibleArea(), returns the area of the widget that is actually visible (considering clipping through containers) - new attribute: independent, makes a widget independent of its container - made textSize attribute protected and added getter methods - string.cpp - new function: Explode(), splits a string at a delimiter - new function: Implode(), concatenates strings from an array - new function: Contains(), true if the string contains another one - stringcase.cpp - case conversion functions are now generated from UnicodeData.txt - added title case conversion function - translator.cpp - new function: SelectUserDefaultLang(), selects the best fit language available - added support for translation contexts - imagereader.cpp - added support for JPEG and PNG images - titlebar.cpp - pressing the escape key now closes the active window - imagebox.cpp - new widget: a box containing selectable images - sha1.cpp - new class: SHA1, implements the SHA-1 hash algorithm - math.cpp - fixed rounding of negative values - cursor.cpp - fixed support for right-to-left scripts - fixed text selection issues - added default context menu - added undo and redo support - cpu.cpp - added CPUID support - fontgdi.cpp - added support for font scaling - fontcairo.cpp - fixed a ressource leak - surfacegdi.cpp - now using clipping instead of buffering to speed up drawing - surfacecairo.cpp - now using clipping instead of buffering to speed up drawing - colordlg.cpp - fixed color selection dialog - tipodaydlg.cpp - made dialog width adjust to button size - charsetdetector.cpp - new class: CharsetDetector, detects the character set of a string - mutexwin32.cpp - now using critical sections instead of Win32 mutexes - access.cpp - new class: functions for threads save variable access - clipboard.cpp - new class: Clipboard, implements clipboard support - timerposix.cpp - new class: TimerPOSIX, POSIX timer backend - document.cpp - added support for parsing CDATA nodes - fixed Unicode filename support - messagebox.cpp - replaced Windows message box defines with own constants - screen.cpp - new class: Screen, replaces MultiMonitor - removed TreeView widget (use ListBox instead) - removed SDL backends - removed LiSA library - added support for path names exceeding MAX_PATH - fixed implementation of callback signals - fixed implementation of Array<> - fixed file IO problems on Windows 9x with Unicows - updated Translator utility to support template files - improved international language support - removed Extended<> template - removed Pointer<> template - improved Linux support - ported to FreeBSD, OpenBSD, NetBSD, Solaris, Mac OS X, QNX and Hurd - upgraded libbzip2 to version 1.0.6 - upgraded fribidi2 to version 0.19.5 - upgraded libiconv to version 1.14 - upgraded libxml2 to version 2.9.1 smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2014000066400000000000000000000000251516402577000226100ustar00rootroot00000000000000ChangeLog for smooth smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2015000066400000000000000000000052271516402577000226220ustar00rootroot00000000000000ChangeLog for smooth 22.11.15 22:34 - smooth alpha 0.8.72.0 - widget.cpp - added mouse jitter tolerance to tooltip code - cache results of GetRealPosition and GetRealSize to improve performance - fixed context menu placement at screen edges - pointer.cpp - moved system dependent code to backends - window.cpp - method Stay() renamed WaitUntilClosed() - WaitUntilClosed() no longer sets the WF_MODAL flag - added SetProgressIndicator() method to control taskbar progress indicator - fixed restoring after maximized window was minimized - windowgdi.cpp - fixed handling of modal windows on Windows - fixed maximized window glitches on Windows 8 and 10 - use asynchronous versions of ShowWindow and SetWindowPos to prevent artifacts - windowxlib.cpp - added drag & drop support - added international language input support - system.cpp - added Reboot() and Shutdown() methods - surfacegdi.cpp - added native Gradient() implementation - surfacegdiplus.cpp - added native Gradient() implementation - titlebar.cpp - do not close main windows when pressing escape - allow dragging windows from maximized state - use a flat titlebar style on Windows 8.x and 10 - image.cpp - cache scaled version of bitmap for display - list.cpp - allow setting marked state when adding new text entries - listbox.cpp - added methods to control scroll position - file.cpp - added support for moving/deleting files with read-only attribute - instream.cpp - removed support for PDP byte order - method InputNumberPBD renamed InputBits - outstream.cpp - removed support for PDP byte order - method OutputNumberPBD renamed OutputBits - translator.cpp - added Afrikaans, Serbian (Cyrillic) and Cantonese (Hong Kong) language support - cursor.cpp - fixed CJK input method editor appearing offset in Windows Vista/7/8 default designs - added support for Ctrl+Ins, Shift+Ins and Shift+Del shortcuts - urlencode.cpp - new class: URLEncode, handles URL (percent) encoding/decoding - config.cpp - added copy constructor for copying Configuration objects - document.cpp - added copy constructor for copying XML document objects - fixed blurry GUI on Windows with high resolution displays - reworked build system to support VPATH builds - reworked hash function API to allow stream processing - removed unused multiple document interface (MDI) code - removed CharsetDetector class - removed support for Windows 9x/ME and NT 4.0 - allow building on PowerPC - ported to Cocoa - upgraded V8 to version 3.22.24.21 - upgraded libcpuid to version 0.2.1 - upgraded libjpeg to version 9a - upgraded libpng to version 1.6.19 - upgraded libxml2 to version 2.9.2 - upgraded fribidi2 to version 0.19.7 smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2016000066400000000000000000000000251516402577000226120ustar00rootroot00000000000000ChangeLog for smooth smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2017000066400000000000000000000033041516402577000226160ustar00rootroot00000000000000ChangeLog for smooth 19.11.17 17:34 - smooth alpha 0.8.73.0 - surfacecocoa.mm - fix hangs on macOS 10.11 El Capitan - fontbackend.cpp - cache computed text extents - window.cpp - added handleSystemMessage callback - windowgdi.cpp - don't update coordinates for minimized windows - windowcocoa.mm - added support for SetProgressIndicator() - system.cpp - added GetResourcesDirectory() method - mutex.cpp - added TryLock() method - added scoped locker class Lock - changed the return type of lock methods to Bool - semaphore.cpp - added TryWait() method - added scoped locker class Wait - changed the return type of lock methods to Bool - rwlock.cpp - added scoped locker classes LockForRead/LockForWrite - changed the return type of lock methods to Bool - jpeg.cpp - avoid temporary files when reading JPEG data from memory - check for JPEG signature before trying to open files - png.cpp - check for PNG signature before trying to open files - crc32.cpp - added method to calculate CRC on plain UnsignedByte * buffers - crc64.cpp - added Hash::CRC64 class to calculate 64 bit CRCs - string.cpp - added ComputeCRC64() method - datetime.cpp - reworked DateTime interface and implementation - http.cpp - use libcurl for HTTP transport - added support for HTTPS - listentry.cpp - added static member: tabDelimiter, use it to delimit list entry tabs - tab delimiter changed from horizontal to vertical tab character - cursor.cpp - performance improvements - tipodaydlg.cpp - tips can now be marked and copied - ported to Haiku OS - removed support for QNX - upgraded libjpeg to version 9b - upgraded libpng to version 1.6.34 - upgraded libxml2 to version 2.9.7 - upgraded zlib to version 1.2.11 smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2018000066400000000000000000000000251516402577000226140ustar00rootroot00000000000000ChangeLog for smooth smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2019000066400000000000000000000061341516402577000226240ustar00rootroot00000000000000ChangeLog for smooth 15.12.19 12:54 - smooth alpha 0.9.0 - application.cpp - new Application::Lock class implementing a global lock for UI processing - widget.cpp - explicitly show/hide child widgets in Show/Hide methods - layer.cpp - use standard widget implementations of Show/Hide methods - menu.cpp - simplified API for adding menu entries - combobox.cpp - fixed selected entry not being updated when new entry has the same memory address - cursor.cpp - fixed text not being drawn correctly after undo/redo - fixed multi-line cursors not responding after clicking below the last line - performance optimizations for text input - scrollbar.cpp - added support for smooth scrolling - container.cpp - new common base class for menus and lists - tree.cpp - draw horizontal branch lines to improve tree look - tabwidget.cpp - added support for displaying bitmaps on tab handles - image.cpp - set background color for bitmaps - hyperlink.cpp - set background color for bitmaps - backendxlib.cpp - allow console applications to run without an X display available - windowxlib.cpp - fixed thread-safety issues with Xlib windows - windowgdi.cpp - added support for high precision touchpad scrolling - windowcocoa.mm - made drag & drop work more reliably on macOS - added support for high precision scrolling on macOS 10.7 and later - surfacecocoa.mm - added support for dark mode on macOS - keyboard.cpp - improved thread-safety - crc16.cpp - added Hash::CRC16 class to calculate 16 bit CRCs - driver_posix.cpp - fixed permissions of newly created files to respect umask setting - driver.cpp - added Truncate() and Close() methods to public API - added IsBuffered() and SetBufferSize() methods to control buffering - implemented Flush() method for file drivers - outstream.cpp - added Truncate() method - directory.cpp - Copy() and Move() method now take a const Directory & argument - fixed permissions of newly created directories to respect umask setting - file.cpp - Copy() and Move() method now take a const File & argument - added methods to change modification and access time - string.cpp - added scoped string format setters String::InputFormat and String::OutputFormat - system.cpp - added GetApplicationCacheDirectory() method - thread.cpp - added GetCurrentThreadID() method - math.cpp - added methods for pseudo random number generation - datetime.cpp - fixed possible crashes - cpu.cpp - added support for querying CPU vendor and brand strings - added support for measuring CPU clock rate - added Float32 and Float64 type defintions - added support for Unicode console I/O on Windows - added stream API to CRC32 and CRC64 classes - performance improvements for CRC calculations - added plain text export to Translator utility - removed support for building with Xlib backend on macOS - removed dependency on libXmu - upgraded libcurl to version 7.56.1 - upgraded libpng to version 1.6.37 - upgraded libjpeg to version 9c - upgraded libiconv to version 1.16 - upgraded libxml2 to version 2.9.10 - upgraded libbzip2 to version 1.0.8 - upgraded fribidi to version 1.0.8 - upgraded libcpuid to version 0.4.1 smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2020000066400000000000000000000104621516402577000226130ustar00rootroot00000000000000ChangeLog for smooth 10.10.20 18:20 - smooth alpha 0.9.6 - surfacegdi.cpp - fixed too high DPI values being reported - surfacegdiplus.cpp - fixed too high DPI values being reported - windowcocoa.mm - fixed glitches after closing tabs in tabbed mode - menubar_cocoa.mm - fixed possible crash after menubar contents change - droptarget.cpp - fixed rare crash related to drag & drop handling - translator.cpp - also look for translations in application data folder - tree.cpp - improved rendering of tree widget in scaled mode - http.cpp - include status code in response header fields - implemented proper multi-monitor support for macOS - added support for macOS 11.0 Big Sur - added a separate error code for denied access to file IO drivers - fixed wrong color space returned in BitmapBackend::GetPixel for multiple backends - upgraded fribidi to version 1.0.10 17.06.20 23:22 - smooth alpha 0.9.5 - threadcocoa.mm - set stack size for new threads to process stack size - surfacecairo.cpp - fixed crash when DISPLAY variable is not set - surfacecocoa.mm - fixed drawing inverted rects with scale factors greater than 1.0 - fixed paint rect calculation for drawing lines - windowxlib.cpp - implemented handling of maximized state and restore - windowcocoa.mm - implemented handling of maximized and full screen state and restore - backendxlib.cpp - added support for theme colors and dark mode - backendhaiku.cpp - load actual app signature from application binary - scale UI to adjust to system font size on all operating systems 22.03.20 11:44 - smooth alpha 0.9.4 - fontgdi.cpp - fixed text length calculation for fonts using kerning - cursor.cpp - fixed cursor positioning and text selection in right-to-left mode - allow compilation for Windows on ARM with Visual Studio - removed support for using Cairo graphics backend on Windows 08.03.20 11:36 - smooth alpha 0.9.3 - popupmenuentry.cpp - react on mouse up even if mouse down was not on the same entry - windowgdi.cpp - fixed drag & drop not accepting long file paths - fixed positioning of IME in non-resizable windows - backendwin32.cpp - fixed black title bar color on Windows Vista, 7 and 8/8.1 - respect colorization tint color on Windows Vista, 7 and 8/8.1 - surfacecairo.cpp - improved HiDPI detection on Linux/FreeBSD systems - translator.cpp - fixed loading translations with different prefix from resources folder - bitmapbackend.cpp - retain alpha channel when grayscaling bitmaps - added support for drag and drop in Translator utility - made editing area resizable in Translator utility - added a button for copying the original text to the translation to Translator utility - also check for _WIN32 definition on Windows instead of requiring __WIN32__ to be defined - adapt include files to work around long path issue when building on Windows - adapt Makefiles to allow spaces in build path - upgraded fribidi to version 1.0.9 09.02.20 16:26 - smooth alpha 0.9.2 - string.cpp - fixed compatibility issues with Windows 10 UTF-8 codepage beta setting - windowxlib.cpp - fixed a crash when placing a text cursor on some systems without an input manager - windowgdi.cpp - fixed mouse events still arriving at parent window after opening popup menu - driver_ansi.cpp - fixed issues with setting buffer size on macOS - backendwin32.cpp - added support for Windows 10 dark mode - backendhaiku.cpp - set locale to user default at startup - button.cpp - draw icons in gray when buttons are disabled - messagebox.cpp - also look for icons in path relative to application directory - fixed text placement when no icon is available - added a Makefile target for code signing - upgraded libjpeg to version 9d 12.01.20 17:52 - smooth alpha 0.9.1 - backendwin32.cpp - added support for Windows 10 accent colors - driver_ansi.cpp - fixed switching between read and write mode - widget.cpp - fixed artifacts when hiding child widgets extending outside their containers - optionbox.cpp - fixed placement of selection indicator - windowhaiku.cpp - fixed possible crash when exiting programs - eventhaiku.cpp - ensure message queue locking is enabled before enqueuing messages - windowxlib.cpp - actually keep topmost windows on top - reset input context before deleting it - fixed interaction with topmost windows when a modal window is active on non-Windows platforms - upgraded libcurl to version 7.68.0 smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2021000066400000000000000000000047461516402577000226240ustar00rootroot00000000000000ChangeLog for smooth 27.06.21 13:24 - smooth alpha 0.9.8 - imageloader.cpp - added support for auto-detecting image formats - webp.cpp - added support for WebP image decoding - windowgdi.cpp - improved scaling when setting icons via SetIcon() - init.cpp - warn about incomplete application shutdown in debug builds - thread.cpp - made it illegal to call Stop on the current thread - fixed thread synchronization issues in wait and exit functions - array.cpp - fixed thread synchronization issues when accessing arrays - rwlock.cpp - fixed thread synchronization issues - combobox.cpp - fixed dropdown staying open when parent window moves or resizes - popupmenu.cpp - fixed popup staying open when parent window moves or resizes - popupmenuentry.cpp - fixed occasional crashes when opening third level popup menus - backendxlib.cpp - fixed timers being invoked in GTK threads despite denyTimerInterrupts state - backendcocoa.mm - fixed possible crash when quitting applications through a dock command - surfacecocoa.mm - fixed rendering of bitmaps with alpha channel - surfacecairo.cpp - fixed drawing of diagonal lines when running in a Wayland session - respect custom DPI settings on Xfce desktop - windowxlib.cpp - fixed possible crash on exit when running in a Wayland session - fixed drag & drop working unreliably - fixed incorrect usage of XGetInputFocus API - application.cpp - fixed determination of binary path on FreeBSD - file.cpp - fixed accessing files via file:// URLs - fixed several instances of undefined behavior found with -fsanitize=undefined - fixed translation field not being focused after selecting entries in Translator utility - upgraded libcurl to version 7.77.0 14.02.21 14:56 - smooth alpha 0.9.7 - backendcocoa.mm - added support for opening registered file types on macOS - screenxlib.cpp - improved multi-monitor support for X11 based systems - surfacecocoa.mm - fixed popup windows appearing black on older versions of macOS - backendxlib.cpp - fixed issues querying GTK theme colors - window.cpp - fixed drawing issues on KDE systems - arrows.cpp - fixed unintentional wrap-around when going below zero value - cursor.cpp - avoid sending two onInput signals when replacing selected text - semaphoreposix.cpp - use custom semaphore implementation based on condition variable - added support for building for Apple Silicon Macs - implemented alpha-blending for drawing bitmaps with alpha channel - upgraded libcurl to version 7.73.0 - upgraded libcpuid to version 0.5.0 smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2022000066400000000000000000000011021516402577000226040ustar00rootroot00000000000000ChangeLog for smooth 21.01.22 19:17 - smooth alpha 0.9.9 - instream.cpp - prevent opening folders with file IO classes - abort InputLine call when encoutering NUL bytes - datetime.cpp - fixed potential crash upon failed time conversion - filedlg_cocoa.mm - fixed incompatibility with macOS 12.0 Monterey - dirdlg_win32.cpp - prepend a newline to caption for improved layout - added support for building Windows ARM64 binaries - upgraded fribidi to version 1.0.11 - upgraded libcpuid to version 0.5.1 - upgraded libxml2 to version 2.9.12 - upgraded libjpeg to version 9e smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2023000066400000000000000000000032301516402577000226110ustar00rootroot00000000000000ChangeLog for smooth 05.03.23 15:38 - smooth alpha 0.9.10 - windowgdi.cpp - apply dark mode to top window edge too on Windows 10 and 11 - fontcairo.cpp - respect text scaling factor in addition to font size setting - surfacecairo.cpp - attempt to read desktop scale factor from KDE settings if GDK query fails - backendxlib.cpp - added support for KDE color schemes (including dark mode) - windowxlib.cpp - improved compatibility of drag & drop implementation with KDE running under Wayland - fixed focus handling for windows without window manager decorations - surfacecocoa.mm - fixed crash trying to draw to windows before they are fully constructed - application.cpp - fixed determination of application path when running under Rosetta - listbox.cpp - fixed and improved list entry dragging behavior - http.cpp - fixed libcurl proxy feature detection - cpu.cpp - fixed number of cores reported for CPUs with different core types (performance/efficiency) - fixed number of cores reported for SMP systems (now reporting total number of cores) - instream.cpp - allow data pointer to be NULL in InputData if number of bytes is 0 - outstream.cpp - allow data pointer to be NULL in OutputData if number of bytes is 0 - various minor performance optimizations - fixed long paths being converted to 8.3 format on recent versions of Windows - fixed handling of long UNC paths on Windows - upgraded fribidi to version 1.0.12 - upgraded libcpuid to version 0.6.2 - upgraded libxml2 to version 2.10.3 - upgraded libcurl to version 7.87.0 - upgraded libiconv to version 1.17 - upgraded libpng to version 1.6.39 - upgraded libwebp to version 1.3.0 - upgraded zlib to version 1.2.13 smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2024000066400000000000000000000000251516402577000226110ustar00rootroot00000000000000ChangeLog for smooth smooth-0.9.11~git20260403.0230c0da/doc/changelog/ChangeLog.2025000066400000000000000000000000251516402577000226120ustar00rootroot00000000000000ChangeLog for smooth smooth-0.9.11~git20260403.0230c0da/doc/other/000077500000000000000000000000001516402577000176465ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/doc/other/deleting.txt000066400000000000000000000016771516402577000222150ustar00rootroot00000000000000There are two ways to delete a smooth object: 1. by C++ operator 'delete' This will delete the object even if some member function is still active. This may lead to a crash of your program. 2. by static method Object::DeleteObject(Object *) This is the recommended way. It will delete the object immediately if there are no member functions currently active and will mark it as 'deleteable' else. An Object that is marked as 'deleteable' will be deleted by the cleanup thread when it is free. You should use the EnterProtectedRegion and LeaveProtectedRegion methods to mark an object as being in use. Do it at least when entering/leaving the Process and Paint methods. This stuff is necessary, because an object may call 'unknown' callback-methods that might want to delete the calling object. If the calling object was deleted immediately, the callback-method would return to the just deleted instance of the calling object. smooth-0.9.11~git20260403.0230c0da/doc/other/include.txt000066400000000000000000000013121516402577000220270ustar00rootroot00000000000000Which files to include in smooth applications? The include files for smooth are in the 'include' directory of the source code distribution. You will have to include one of the following files: smooth.h - everywhere smooth/main.h - for normal applications smooth/dll.h - for DLLs using smooth Examples: You have a project (normal app) consisting of three files: main.cpp - includes smooth.h and smooth/main.h tools.cpp - includes smooth.h if needed tools.h - includes smooth.h if needed You have a DLL project consisting of the following files: dllmain.cpp - includes smooth.h and smooth/dll.h tools.cpp - includes smooth.h if needed tools.h - includes smooth.h if needed smooth-0.9.11~git20260403.0230c0da/doc/other/standard.txt000066400000000000000000000007251516402577000222130ustar00rootroot00000000000000Standard behaviour of some smooth functions - all objects should use the Object::GetRealPosition method instead of calculating their position on their own Return values of standard methods in exceptional cases: !registered !visible !active Paint() Error Success n.a. Process() Error Success Success Show() Success Success Success Hide() Success Success Success Activate() Success Success Success Deactivate() Success Success Success smooth-0.9.11~git20260403.0230c0da/doc/other/version.txt000066400000000000000000000005251516402577000220760ustar00rootroot00000000000000The version number of a smooth release can be interpreted as follows: In 'a.b.c.d' the 'a' is the major version number, the 'b' is the minor version number, the 'c' is the release number (starting with 1) and the 'd' is the patchlevel (starting with 0). So 0.8.13.4 means smooth version 0.8, 13th release, patchlevel 4 of version 0.8. smooth-0.9.11~git20260403.0230c0da/doc/reference/000077500000000000000000000000001516402577000204635ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/doc/reference/aboutsmooth.html000066400000000000000000000041411516402577000237150ustar00rootroot00000000000000 About smooth
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

About smooth

smooth is a cross-platform C++ class library. It provides application developers with everything needed to build state-of-the-art applications. smooth is fully object-oriented, easily extensible, and allows true component programming.

smooth is available under the terms of the Artistic License

smooth is supported on the following platforms:

  • Microsoft Windows - 95, 98, ME, NT 4.0, 2000 and XP
  • Unix/X11 - Linux and possibly some others (no GUI support)
  • QNX/Photon - RTP 6.1 (no GUI support)


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/doc/reference/callbacks.png000066400000000000000000000067631516402577000231240ustar00rootroot00000000000000‰PNG  IHDRŖca0( nIDATxÚí?hãJ§<ĸ;ŽËãå%9’­˛VuGˆÂ‹‹ÜF{ˇQžĪ0›#̆ŲE§úc”™†wlڅČLFvÔŨĨFĀĸ4ˆ‘饎ŠĘÅ ĄBGnŅpd•š­Čę}7#XėĘrī FÖ;§ ģŪ‘ŊM!ŋ X†’˜ÍŒ&ië>rH‰`¤æ˜Køéu%čõäė›Žc3ē9ŽĒw&#ŗË\Ģ7fiģ†šô2¸ą˜Ō ąŽÛC}T¸ĪTŠšF'\ĩ‰Ā^F/FWÜQv×âsŒü áĄc¯™]—°ėšhēY˙Üī˛ļŪ)džąë0O ÁSĸÆŦÜQ#Åpē#͋‘šËĀZąķƒ>ŒJPļR#î :ą:$ŖKf˙3ķŲ%Ī1Ē1 ģßŸŅŽ›‘€;üō2Ȍ%ŋˇœ’ŅUE&Žä`tŋĩƒ9üŗÃÉn>XqĪa§;ÖÁQngåw;ˇjĨXíËĪ gƌGhˇ+÷fŲ8^›ųÁ@F›Fŧ" ą0œŨ‘csÂ* &õF2ŧ”IFEN†Š5é3ôŠbĨqč#ÜÞ‰œîɨŨŊÎp…”)¨‚õ™`´#“_ģÛ+Ŗ22öCší3››(?ÛŧQw?d„âLÕÍhöÁcŗ´]‡qBwøR Œˇ)0MÆĪžŠ$ˇ\Œd'͆ޞsoŌ‹™q8^­N÷`””=ÁDPQšfbˇ BĖÆgdíXsÖ.QG™‚šŗ>Œ6ĢnF9{qÂūSĩĄ—UÍxdäĄ]ŒšđâWŠdÄFsØbS5]eĪaI/“rš(ی ¯6Q§ôd´>ōŊ ö6;&#gOĄ‹ĖĘj°Z4=ÅLl÷÷ĖŽwö¸ēëđŽļēk†1ĢzŒŦų\‚ĻĨžŒ cßâļĘÅ¨ĶyĄuoŒœu‘āäŪ\ō`$ĨÆ­4^ŒŪRX˙zŨŒČõÅāÎtĒ}u˜›KęFMÛėˇÎ¨N{‹Æ’Ŧ#}N3௎›ÅoŅ ˇũĮÜ^2#āŠ–ÅˆQāŒZã vuô5,”X#b8#==Vf—‡ë9ú„3â8įÕˇĀK3’ct$tëN>DŒB`¤Ī1Í§zĻĨ˙#F!ŨŸ^÷`TŊ#ÕÁŠ9ÔųšĶŊķ6ŸoqåøīS™ãĘO$Ŗ‡=îœPX%‘ōˇķ/Ø_Í0Ú+ßËH_ų +YŖšūbp;t›CK’[Á!zS&íÁ_…U*ļ¸zxûĨđMŨŒ:`Ä9’0uaŪåīę°šĖ?r_ônëņ‘į—/đe+Ŧ’÷ô+bĻ“7č)æĖĶÍH/ļ‘¯Jf7úÉ_.û6īqzũđ\<¯ëOnFđĀžŖ°JrÜ9ˇ÷dÜ"”ŖŊKÛ^Œt~”Į´ãæHwęw+BH6 „Ívđx~¸åfdjI…qĮUĖeĄDÍĩRænFZzøMHíĨŋu(iŋÛŽjáÛlyF›­˛#—Âbû˜>ū> ģũœŅģ˙ÛK‹fÛ ßÛ“RØ6#Ī…ÃŲĘ܌žt‡\ T’ãę‡VGƒ Ú}įÍBn¸k.1ÖHį˙™4ĄØ,’6ru˜\ŖLāĢ^w3ĒčįÜĄŖpJĸĪæöîĀ;’`f8Ö9Ģ͆zŖˇ: ÛaŅ^ܰmŽãŒúQ˙Õ¸1€d„䋪°JųCŝ~blåcÖŨ<Ž™ˇVH<ë0d-D {4žx …n3œ™™éÃ!ˇu^?Ŧیë[hk+Ŧ’¯-#ŗĶ Á>Ė­7“:EŲ^FČa˜ƒËKĶ%ҞNEÂŗY`Š48dƒëv>Ļ(ü/FēöO ôĨÔ˃ŦŠ”ŗZI ŨfßÃķúl`]߉$č eOFēūŸ?ŧgä]tōæįnęi•E–eS –]Ĩ` i9,›i Īḱu}×ÔæũŽXh6S“bŒä˛ēØd§UŋõļŽÍ§ ŠFŊËķą5Wč|]ŋĮטmSˇųŦÛfš"ĨĀĸąiˆČķĶāCWk_ÛīZJoŠÚ\ō˛™Žt¤=–Ķ™2˰lą÷W_ßov¤ÛlÄ(’ˆQÄ(’ˆQ$Ŗo‘‘8’YrUįÕ§‚ˆr¨Œ xR‘ėDŒ^-ŖeŊ‘…ˆŅĢeTĀŋĪ+!¯kY˛ɨ5oüz¯ĨŅÅ$@Ã"ŌÖÄ2>^Đ"‡ˈÁßTj†ųŖ,Éh@jKSÃÃĸ†´­$ŒãLäЀ9ÃV Ĩ9Î!,e„ÆÖd¨e⨀Æ4[ÚwD”ãu@2ōh8ë šÎ_c’Œ”uG#™KFį*´ŒãbäŅ€áõ:ô<ÚV$E)#،2)‰Ø4‡Í˜sX r•āj>B<ŖH"F‘DŒ"F‘ŧŒüę’Ū%4ž›@tEXtComment Image generated by Aladdin Ghostscript (device=pnmraw) ';IENDŽB`‚smooth-0.9.11~git20260403.0230c0da/doc/reference/credits.html000066400000000000000000000042551516402577000230140ustar00rootroot00000000000000 Thanks!
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

Thanks!

The following have provided bug reports, suggestions, patches, testing, or done us other favors. We thank you all:

Evdokios Sountourlis <sountourlis@gmx.net>
Hendrik Lönngren <hendrik@loenngren.de>
Hrvoje Horvatic <hrvoje.horvatic1@zg.hinet.hr>
Robert Kausch <robert.kausch@gmx.net>

<TheMartian@onebox.com>

Please report to robert.kausch@gmx.net if you think that your name should appear on this list, but doesn't.


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/doc/reference/dtds/000077500000000000000000000000001516402577000214215ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/doc/reference/dtds/configfile.dtd000066400000000000000000000010411516402577000242170ustar00rootroot00000000000000 smooth-0.9.11~git20260403.0230c0da/doc/reference/dtds/langfile.dtd000066400000000000000000000005541516402577000237030ustar00rootroot00000000000000 smooth-0.9.11~git20260403.0230c0da/doc/reference/howtoget.html000066400000000000000000000041131516402577000232100ustar00rootroot00000000000000 How to get smooth
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

How to get smooth

You can get the official source and binary distributions of smooth on the official website at http://www.smooth-project.org.

smooth is distributed under the terms of the Artistic License. You can contact the author under robert.kausch@gmx.net if you want to make arrangements about different distribution terms.

For questions regarding the smooth distributions, please contact robert.kausch@gmx.net.


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/doc/reference/index.html000066400000000000000000000116521516402577000224650ustar00rootroot00000000000000 smooth Reference Documentation
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

smooth Reference Documentation

General Getting Started What's New
API Reference Modules Overviews

Miscellaneous Tools Appendix


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/doc/reference/lgpl.html000066400000000000000000000654561516402577000223270ustar00rootroot00000000000000 GNU Library General Public License
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

GNU Library General Public License

		  GNU LIBRARY GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1991 Free Software Foundation, Inc.
    		    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

[This is the first released version of the library GPL.  It is
 numbered 2 because it goes with version 2 of the ordinary GPL.]

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.

  This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it.  You can use it for
your libraries, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.

  For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

  Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.

  Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library.  If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software.  To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.

  Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs.  This
license, the GNU Library General Public License, applies to certain
designated libraries.  This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.

  The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it.  Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program.  However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.

  Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries.  We
concluded that weaker conditions might promote sharing better.

  However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves.  This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them.  (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.)  The hope is that this
will lead to faster development of free libraries.

  The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, while the latter only
works together with the library.

  Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.

		  GNU LIBRARY GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License").  Each licensee is
addressed as "you".

  A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

  The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

  "Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.

  Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.
  
  1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

  You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.

  2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) The modified work must itself be a software library.

    b) You must cause the files modified to carry prominent notices
    stating that you changed the files and the date of any change.

    c) You must cause the whole of the work to be licensed at no
    charge to all third parties under the terms of this License.

    d) If a facility in the modified Library refers to a function or a
    table of data to be supplied by an application program that uses
    the facility, other than as an argument passed when the facility
    is invoked, then you must make a good faith effort to ensure that,
    in the event an application does not supply such function or
    table, the facility still operates, and performs whatever part of
    its purpose remains meaningful.

    (For example, a function in a library to compute square roots has
    a purpose that is entirely well-defined independent of the
    application.  Therefore, Subsection 2d requires that any
    application-supplied function or table used by this function must
    be optional: if the application does not supply it, the square
    root function must still compute square roots.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.

  Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

  This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

  4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

  If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

  5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

  However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.

  When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

  If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

  Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

  6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

  You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

    a) Accompany the work with the complete corresponding
    machine-readable source code for the Library including whatever
    changes were used in the work (which must be distributed under
    Sections 1 and 2 above); and, if the work is an executable linked
    with the Library, with the complete machine-readable "work that
    uses the Library", as object code and/or source code, so that the
    user can modify the Library and then relink to produce a modified
    executable containing the modified Library.  (It is understood
    that the user who changes the contents of definitions files in the
    Library will not necessarily be able to recompile the application
    to use the modified definitions.)

    b) Accompany the work with a written offer, valid for at
    least three years, to give the same user the materials
    specified in Subsection 6a, above, for a charge no more
    than the cost of performing this distribution.

    c) If distribution of the work is made by offering access to copy
    from a designated place, offer equivalent access to copy the above
    specified materials from the same place.

    d) Verify that the user has already received a copy of these
    materials or that you have already sent this user a copy.

  For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

  It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

  7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

    a) Accompany the combined library with a copy of the same work
    based on the Library, uncombined with any other library
    facilities.  This must be distributed under the terms of the
    Sections above.

    b) Give prominent notice with the combined library of the fact
    that part of it is a work based on the Library, and explaining
    where to find the accompanying uncombined form of the same work.

  8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.

  9. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.

  10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded.  In such case, this License incorporates the limitation as if
written in the body of this License.

  13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

  14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

			    NO WARRANTY

  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

		     END OF TERMS AND CONDITIONS

           How to Apply These Terms to Your New Libraries

  If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change.  You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).

  To apply these terms, attach the following notices to the library.  It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.

    <one line to give the library's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the 
    Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
    Boston, MA  02111-1307  USA.

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the
  library `Frob' (a library for tweaking knobs) written by James Random Hacker.

  <signature of Ty Coon>, 1 April 1990
  Ty Coon, President of Vice

That's all there is to it! 


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/doc/reference/license.html000066400000000000000000000307171516402577000230030ustar00rootroot00000000000000 The Artistic License
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

The Artistic License

                            The Artistic License
                         Version 2.0beta4, October 2000

                         Copyright (C) 2000, Larry Wall.
        Everyone is permitted to copy and distribute verbatim copies
         of this license document, but changing it is not allowed.

                                  Preamble

This copyright license states the terms under which a given free software Package may be copied, modified and/or redistributed, while the Originator(s) maintain some artistic control over the future development of that Package (at least as much artistic control as can be given under copyright law while still making the Package open source and free software).

This license is bound by copyright law, and thus it legally applies only to works which the copyright holder has permitted copying, distribution or modification under the terms of the Artistic License, Version 2.0.

You are reminded that You are always permitted to make arrangements wholly outside of a given copyright license directly with the copyright holder(s) of a given Package. If the terms of this license impede your ability to make full use of the Package, You are encouraged to contact the copyright holder(s) and seek a different licensing arrangement.

                                Definitions

"Package" refers to the collection of files distributed by the Originator(s), and derivatives of that collection of files created through textual modification.

"Standard Version" refers to the Package if it has not been modified, or has been modified only in ways suggested by the Originator(s).

"Modified Version" refers to the Package, if it has been changed by You via textual modification of the source code, and such changes were not suggested by the Originator(s).

"Originator" refers to the author(s) and/or copyright holder(s) of the Standard Version of the Package.

"You" and "Your" refers to any person who would like to copy, distribute, or modify the Package.

"Distribution Fee" is any fee that You charge for providing a copy of this Package to another party. It does not refer to licensing fees.

"Freely Available" means that:

       (a) no fee is charged for the right to use the item (though a
           Distribution Fee may be charged).

       (b) recipients of the item may redistribute it under the same
           conditions they received it.

       (c) If the item is a binary, object code, bytecode, the complete
           corresponding machine-readable source code is included with the
           item.


         Permission for Use and Modification Without Redistribution

  (1) You are permitted to use the Standard Version and create and use
      Modified Versions for any purpose without restriction, provided that
      you do not redistribute the Modified Version to others outside of your
      company or organization.


           Permissions for Redistribution of the Standard Version

  (2) You may make available verbatim copies of the source code of the
      Standard Version of this Package in any medium without restriction,
      either gratis or for a Distribution Fee, provided that you duplicate
      all of the original copyright notices and associated disclaimers.  At
      Your discretion, such verbatim copies may or may not include compiled
      bytecode, object code or binary versions of the corresponding source
      code in the same medium.

  (3) You may apply any bug fixes, portability changes, and other
      modifications made available from any of the Originator(s).  The
      resulting modified Package will still be considered the Standard
      Version, and may be copied, modified and redistributed under the terms
      of the original license of the Standard Version as if it were the
      Standard Version.


 Permissions for Redistribution of Modified Versions of the Package as Source

  (4) You may modify your copy of the source code of this Package in any way
      and distribute that Modified Version (either gratis or for a
      Distribution Fee, and with or without a corresponding binary, bytecode
      or object code version of the Modified Version) provided that You
      clearly indicate what changes You made to the Package, and provided
      that You do at least ONE of the following:

       (a) make the Modified Version available to the Originator(s) of the
           Standard Version, under the exact license of the Standard
           Version, so that the Originator(s) may include your modifications
           into the Standard Version (at their discretion).

       (b) modify any installation scripts and procedures so that
           installation of the Modified Version will never conflict with an
           installation of the Standard Version, include for each program
           installed by the Modified Version clear documentation describing
           how it differs from the Standard Version, and rename your
           Modified Version so that the name is substantially different from
           the Standard Version.

       (c) permit and encourage anyone who receives a copy of the Modified
           Version permission to make your modifications Freely Available in
           some specific way.                                               

      If Your Modified Version is in turn derived from a Modified Version
      made by a third party, then You are still required to ensure that Your
      Modified Version complies with the requirements of this license.


      Permissions for Redistribution of Non-Source Versions of Package

  (5) You may distribute binary, object code, bytecode or other non-source
      versions of the Standard Version of the Package, provided that you
      include complete instructions on where to get the source code of the
      Standard Version.  Such instructions must be valid at the time of Your
      distribution.  If these instructions, at any time while You are
      carrying our such distribution, become invalid, you must provide new
      instructions on demand or cease further distribution.  If You cease
      distribution within thirty days after You become aware that the
      instructions are invalid, then You do not forfeit any of Your rights
      under this license.

  (6) You may distribute binary, object code, bytecode or other non-source
      versions of a Modified Version provided that You do at least ONE of
      the following:

       (a) include a copy of the corresponding source code for the Modified
           Version under the terms indicated in (4).

       (b) ensure that the installation of Your non-source Modified Version
           does not conflict in any way with an installation of the Standard
           Version, include for each program installed by the Modified
           Version clear documentation describing how it differs from the
           Standard Version, and rename your Modified Version so that the
           name is substantially different from the Standard Version.

       (c) ensure that the Modified Version includes notification of the
           changes made from the Standard Version, and offer to provide
           machine-readable source code (under a license that permits making
           that source code Freely Available) of the Modified Version via
           mail order.


        Permissions for Inclusion of the Package in Aggregate Works
  
  (7) You may aggregate this Package (either the Standard Version or
      Modified Version) with other packages and distribute the resulting
      aggregation provided that You do not charge a licensing fee for the
      Package.  Distribution Fees are permitted, and licensing fees for
      other packages in the aggregation are permitted.  Your permission to
      distribute Standard or Modified Versions of the Package is still
      subject to the other terms set forth in other sections of this
      license.

  (8) In addition to the permissions given elsewhere by this license, You
      are also permitted to link Modified and Standard Versions of this
      Package with other works and distribute the result without
      restriction, provided You have produced binary program(s) that do not
      overtly expose the interfaces of the Package.  This includes
      permission to embed the Package in a larger work of your own without
      exposing a direct interface to the Package.  This also includes
      permission to build stand-alone binary or bytecode versions of your
      scripts that require the Package, but do not otherwise give the casual
      user direct access to the Package itself.


        Items That are Never Considered Part of a Modified Version Package

  (9) Works (including, but not limited to, subroutines and scripts) that
      you have linked or aggregated with the Package that merely extend or
      make use of the Package, but are not intended to cause the Package to
      operate differently from the Standard Version, do not, by themselves,
      cause the Package to be a Modified Version.  In addition, such works
      are not considered parts of the Package itself, and are not bound by
      the terms of the Package's license.


              Acceptance of License and Disclaimer of Warranty

 (10) You are not required to accept this License, since you have not signed
      it.  However, nothing else grants you permission to copy, modify or
      distribute the Standard or Modified Versions of the Package.  These
      actions are prohibited by copyright law if you do not accept this
      License.  Therefore, by copying, modifying or distributing Standard
      and Modified Versions of the Package, you indicate your acceptance of
      the license of the Package.


 (11) Disclaimer of Warranty:

       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT UNLESS REQUIRED BY
       LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER OR CONTRIBUTOR
       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
       OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
       OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, PROFITS; OR
       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
       OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
       EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/doc/reference/pictures.html000066400000000000000000000132601516402577000232110ustar00rootroot00000000000000 Pictures of most smooth widgets
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

Pictures of most smooth widgets

Most of these widgets are shown in either Motif or Windows style. All widgets are supported in both styles (and other styles), but for clarity we just present a selection.

Below we have three views seperated by QSplitters. At the top-left there's a QListBox, at the top-right there's a QListView with a QHeader and two QScrollBars. And at the bottom there's a QIconView.

Below we present a QMainWindow which has a QMenuBar and some QToolBars that contain various widgets, e.g. QToolButtons and QComboBoxes. The central widget is a QWorkspace which is used for MDI window management and which contains an MDI-Window featuring a QTextEdit. At the bottom you see a QStatusBar and at the bottom-right a QSizeGrip.

The image below shows a QFileDialog. On the Macintosh and Windows platforms you can either use a QFileDialog or the native file dialog. This is explained in the QFileDialog class documentation.

Below is a QPrintDialog. On Macintosh and Windows the native print dialog is used, but for other platforms we provide QPrintDialog. Use QPrinter::setup() for portability instead of the QPrintDialog if you need to be platform independent.

Below is a QFontDialog.

Windows

The screenshot below shows a smooth::ColorDialog.

Messages are presented using smooth::MessageBoxes, as shown below.

The image below shows a QProgressDialog. The QProgressBar can also be used as a separate widget.

In the screenshot below we have a QGroupBox that contains a QLineEdit, a read-only QComboBox and an editable QComboBox.

The screenshot below shows a smooth::PopupMenu.

In the screenshot below there's a QButtonGroup containing four QRadioButtons and two QCheckBoxes.

The screenshot below shows a QTabDialog. The tabs (QTabBar) or the more convenient class QTabWidget, which combines a tab bar with the pages, can be used separately. In the visible page you see a QLabel, the range controls QSlider and QSpinBox and below a QLCDNumber. In the bottom row there are some QPushButtons.

In the screenshot below there's a QTextBrowser displaying a HTML page. See also QTextEdit.


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/doc/reference/screenshots/000077500000000000000000000000001516402577000230235ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/doc/reference/screenshots/colordlg.png000066400000000000000000000323551516402577000253460ustar00rootroot00000000000000‰PNG  IHDR´mŅw™*tEXtCreation TimeSa 9 Mrz 2002 22:49:01 +0100‰=ætIMEŌ 3Žoƒ@ pHYsÃÃĮo¨dgAMAą üa4FIDATxÚí}[¯-ŲuÖË­–, J¸Æ8WĮ‰ŨÁq‡Äá.Bâ%ųŧĸĶÉi‚ā87oˇCBNãøHá-Ņ-YÛÛ$R›´m0!$0ą“–,Y!ÅZģöĒ=/ã6gÍZUkīīķöîycĖšÖ^õoŒĒUE¯Ŋú‘Dxū…÷<ĩ˙Ī;ŪųŽĩw°ŧøâ‹ûßOO|üŖkī`CxjjA?pĮņäņŖ{÷îí§â‰?ôÖûûßD‡_7 ēęė{W˙™ū5Ļ˙EöY”d¨ zŨ–.ĪV˛S¸4¤¸tēS~ɛ˜Ü3îÕđo‹¸tąéė/RÄßa_ĖĸE?¤Ŋ-ÉîŽ=ôøVãØö LÖÁ'°é"ėPāŠų!ēã÷?ņĪOŗĐũ˙åĮžXŽƒØ(Ļōß*ĐČņ÷>ũÁ¸ûUßūÒå˙}íŸėÍwü%ļøß?ō3ûßoųîos˙Ī—ûßoũËī_boÜVˆäøúgĖø‡ßöCcqķw?õ _úOPøqSøė‡ßˇ˙ũ-÷ŋßzīÅŠö ā„7­ū#ßöÃz`{xéåWĘÁüŋ16žyöšũīøĢ€å‹–šã?ųxj˙ŅwŧÍ~á?ūüÔūcīüģûß˙ûÕ4v˙ğû{™ņ˙üĩGcãO˙…÷ŒĪėNŗo~îĮ2û˙ö+˙`jÃ÷ü䨸ÜŋģI™ŋųû.Ļöš|ߡÜ{1NĢ?ķĄ÷NŗßöWĄ>õK?Įû_˙™†7€ÍbO‚{6Ü˙ŒlčdÆĐp)Ī—Ž˜ņĢßūā̝hņw>ņOãŲ/üƁŋöĪūČ׎´øņ°Ū7žûŊßôî ~ößž8Ųiõ„‘ßöũ?õļŋrpĖhņÛ˙Ú!ø'˙MNĮl{˙dŗ-ú™1Ŧ{ļúOūųŋŋįĮŊxÜķ#EI{,KÄâ1Ã7}ßE[ę?2#ˇŖ~ nf Ģ_Ęŗ§Å=9îĻ´:\)Įüû öĘ1ŊĀĀȌcŖŗrüŨO} ¨Wķ4`JĢ÷ä¸OĢc~Üãˇ?zČŠ˙Ės|ž;æÔßđŊ?ū×̜:.;p  Ÿr1kƸū¨C$Į7}ë흿ƒŋ÷é_˜FFfüǎ?øŌ'Oįd'd"ųö5ßņ#_øŸ˙?Įs2‡2ōIî)­Į2_÷]īųüĮ~vJĢßü܏ÅÎoųî˙­_ũé)­>œĄđßûŪĪũōû§s2#3~ķ_zßg?üžņ„Ėäū­ß˙ūĪ|čŊŸūĐ5ŸŽ'd¸`ŲsD–MgįgĐŪâī|×'>ūŅũoÜx7žĀ'Î÷˜ŦsūŸĀ˙÷ÉqšoČėŠīúëƒDŋķ+ŋ¸_tOĩ———¸ņ|ˇ€-âūƒ‡ënäĀņĪ~éķ‡˙œ˛°“↟<~ôsĪŋeí7ä\0 ˆ0Dŋ›=–nČqŨģl IZ}yyšö~VÃũ§§ >•MŦŊ7€M !Į'­Ŋ€Õ D(G 9NÉ6Āž!ĀäĀäĀäĀ€˙n5ŽNƒøšÛ ŸŊ.An1đūč(ߟâ'žá=Wßáσē<üöĩŨŨqĐ׎Š?ļ7lŸÛ{5üíč?°Îk‰|īŗÖŪĒĀ]‚ö¯~ķŪÚŨVĀžÉĪ?¨|“o/îūÆŪwåĄčwƒ‹Ķ‘ÔßUÆŦŖß%u§VĮÆg¸ÃtˇŅ“ŽË82x:ĀÚ8Ë[–Uq/¸wlØôÛrÖĮ’äЃēã°JÖēgZ¯Íąģú+B͕u掆cB\ĒQ×)Į7XK‘#ąũĻ“BËŋsZ™Ęû;ô#Ž&ōm`Ō!䨴ˇēĨĨÁPŽĀúčLŽÕŒ×Ā}učüÃ~ÆĄ;Ÿē_Ë0ô§rūķũMS€õ҇Ē^WØķÚđr5ĮaAŽĀú˜EŽ]ŽŽų2°KyŽ‹Œšŋ“ĶŊĢæxē×Â5G`}´“ãfœÉĒk-}ĻÛfŨũĘqmC9ëC%ĮŪ˛ĸYŒ´Éēf1¸ā>7ķļ ĩgĢ—ûŖ39ëŖE96ȸlÍeØęÆŽrÖG59ú?č‡DĨ*ņ+ĻÜrĄ°åī…ÂFŋÉņŠųļWŽģËRyũ5͒jŽĀú¨#Į%˜ą{åk­€g÷ZČmyĘ×r(G`},r8éĨJšĘ/a´ÕjCu•NŊæŲ›k˙îëyV( G`}ô'GĘZÜaāÆņfÆŠ%Á}ú]qü›k™ûiæ÷ZCālfäûžĶ;ü~€õQAŽ&Ŗå}§ģtä(<Į°š=§{ Gču@SlzãËĢč¯1ލ9úÉÔÍėÔ°=¨9ëŖ›rœSšYüZkéÍnĖãŽ\į¸âƎ€rև—íC‚j|}u@*ŒíœÚ!R yUē¸ÅŖ’ZęY°kKURŅÜíФōČŊ[!2ŗ% G`}tPŽDęlÖōą[s‚L\43ĻAyėKPõž4ęŖf{š4Ú ĮėŊœņŽå9ëc9’üņ.),gLĩhĘ%ŠËœ˛Į§ÆšœŠä5”Ĩŧ4Æáâ„ĐÂ_&ų^׃Ŋaíĩ[my- PsÖĮb÷sTD_Üĸb<5āã¨JPJ¨ŠˆĀĮŅÉ"XėD>*yDâÖZĘk Š!đĢ×rēëĨ鯚”#°>\äHį0žŠÍœÁ&‡Ím2Â\rŧ˙āáũ™!n5ŽŪŸ‡ķãÜn´*GųîՌlOɯe!Y•&Û rä_+YeWĨ­Ē„›$=+Nw¯R¯UúQ*žž@9˛OÚ&āũņ ķ-ËÄA–šâqîNBĖb˛Ų4›˙†bKąYōõsKa^fčRda7m%5ĮJ6Ô^QÃËd€š#°>ęɑęĻxjãė5jK§ĘAž+ÍAVéŖ M ûTqœą‡Pŗtë~ZÉ5G`}4*Gŋllöík†%˛‘a˜­û‹MrÖG§ŗÕTy`1X&Ũ}%d™Ģ։ĮP-ŽšeŖ3‡%sY’~|NˇąhĘēíČX >ˇēL¨ã#ķf$¤ĸÅ0TfãaIayHSãĮ 2š‰€DŦLo÷Â1ųnõ v Z䈚#°>lr4Ō"âl8!ir%C^Åz]¨“áč^Lڗ8œäB-\Ė>&ÁdÃEöĪĘX'矪9—ģ =‚ttIrnpyyšDØûę—4õønĩiā׌YLˇ<ŦS‹fŪ Ŋ ˛ĩ¤™„šŌŌTaÕĸō¸Ģéfˇëo’ČąŪņÎwąãO?ēwīŪÚģķbOd§_´†Ų ē°!ĨËō šáę,Š%ø”'{-“õ.ŸV‡n¤C ŋ82ëœCōŨęZŠäģm›g€šcOā’ī6ĖPŽWųT1]Ťb×Á\ĸ´ôwY.ĐģTŲ ÃÎé˛Ûžę”Ŗ<Ë2f#wˇ#”#°>úÕ4IÎî8æ˜U]ęŨĪ\!xˆl V˛--GĻÎerÖĮnšĐUĸ˛šK'éŌIē$t—XôZ9ʋöíJ?žŽüņĖŗĪ)]āLA‘üĄ’Yf=šUįŦvK!cõkē,WģŒ^ēbŊ˛č*{Ö^B* ˜6âŧôŽ3ŊÎQŅ­~›ŧíjWWŽ_o5xc•5pÎ`ųn§ez¤ÕEŨx–ÔnúzĘJ%§nŖZ…[ŗn1ÔĶæĨw ¯a˜Íz3¸R'Į¯„:€īFœO|4‘Ŗĩ1’GIîōęŌéåwm^eˇF9ÎgÅÔ{M7ž ‚›^}ɸ㘸r’û‘}û¤iu˛ĄŲf$›ŅIĖNļĐÍâšãé÷ÔF_rl¨3žôō+]ˇ°&¤ëˇđ2/..ē\f”qb¯íõ9[-Š5njŽž7dŠwŒCĮšc\p,ģĀ™B’ŠēY-æ’ŖS 8ûę2DSŒ‡Ąg´™{ËålŊOȐ5 iIŀŌÉ9ä6 ŪĀƒ3 |˛Ņ/5Wlæēæ¨†Ē’ŪŠ˛ČØ*ÉqĸĶĒP¤Y_ũ—‰Ö¸Ėcā¸`ˆÍčŲk†XK‘G‚F(fJŪ–ŧ›´ß ŧŽUg¤á ĮĶãÉãGkoá\ŅĒM…˜ō*L˛ …ĨÂe~KáŠČFĸ$Õ2hÔĀŗIđą‰PŦŖČō:G‡‹¸7ŋĨ Ė3ôŊÎņŽãŒîh+a•;Ũ†™i5š\xēô nÖe;ģõÔOöžd€rbŦu=æėš#5ĖgËÔۗb뚱B˜ĩ ĪēŪāæ{ .ņĀ=ĨöÉälÕĘŅ™5”×@.V#¨lXG”JÃÍ&NZi&šZ™5ÆoČ,ē1×~8 æl‹ß•§´'3ÂŌ׃‹ģąķ Ã_ãŲę™ [ũ”#p>8ÅŖYũ<ųœĢtyšāÎU†:]ųĩ”9[@Ī‹Āo>÷>Ĩ&6œĢÔ,×ŗ1/ųÍę*Ë5îdáåD ÉälŨ“4jfĻ´ ĨtxwãHHŗ#]5Žkށ™˛éVģ“#jŽ@ŒËËË%ÂŪđPŋHhîsĢ•áŧĄ˛›kĄ´ÁS’žŪčÉä>ąá\ČÃ2ÎU‹ĪVW[˛5l(ĮCēįã“Į6r ų*ׁwģņDj´ƒx]‚dģ¤Ąæ¸Đ–J€O[|ãÛfԓcŦŅ,ŗ¸aĐ7]•57‹ĮŠ|š† )°_HæúĢFÄŲ’mČÃې^‹OB*+rļ€YĪ­f d*LēŽēĄ˜5OD&Jb—¨§Åœŋ‚qËŲ´ŋˆiĶ ģVÆn&/)ėæ:Įx ‹…ũįpü,Y5G` ÉņpŸČĢ˙_} 7iS× y0ņ•ƒäƒŠŊ=8ް[å"k[ö/n•lī˙÷Ŋ[eßeĢÖß+übxōOĖũÛDeĢæßëöƒŋV~özú ît{k?˙ {ūjö`ëE“@Wēâ hwh\ũCOWíĢÆÕøuãj<ĐŅŦ°ã„Â>Ž ûk˛#nŨÃ8ˇîĩ}ąnbĮ ;Rםöœ­;í9[wzíŲēW–o(×Ŋą¯\wÚsgz¯ĸu“ŋŅßöÂũúũōo”­;ŊWŌēŗ>;z7÷ŲëHŽ{fœ81ngŠōQÔ1ũŗu.û€-j'՞¸&[@,–ÉûØÉSÚ8N™,ë9r§LŗåØüˇH„Ĩ›ŠcęÅJ_.,ĨĀãė0qŠ€z3ŠoHĢĒ9‚o2aŖīCĢÃÜŗÕ¤ô„˛cQdt–5Šâxųą‰%KW­°™"ũˍŲ8°Pp˙Î9 æl-äH ĶÅ%$Xf˙$䚑)SaĶāY.ϤuzužuŅĩÃĒõt)Ŝî>?æWÃ>9tTŽ{ĩØPs|éåWúmá  <ÛzҎâââĸ×%DąlŒŸG8ũž[­ķWllr"q1‰‹iRĄ%÷*PÎpyôņĻ+”BĻnnʨmđyĩ1/ŋŊ5Č1Dœč¯9îÚŽ[8cœé[!ŽŠBīlU‚îēBwznõr 9]JŦ~ã]ģ"ZQŽgņVt¯6Žh"Į89MÆÔŽUmĖNŗxrŪ\čéaĨœēŒPĢkåaVOąS}įRYaąŒ”#+y-ŠĒE—†e7ÆĄcÍg¨ī zqå2ʑM‡9ƒ%ÔyÅCznž‘ VĪŠĮY*™zra›ė|)ļ'uõ¤ÆųŲ•‰āI„;ī‡Ãę5GāŦךι9F &L醱aubėČrĸäXhÉÜąā)CW6(ĮĀq„MІZ4Uģ)Ŧ4ėt:ëéČâéĐāÄۇŒōJ܄r´tĄ88Ķąaš›O6Øæ(ÕOŋm]ÉÚĐ'­öäÂąI~´° l¤œô DŅ_zĒ "KBéP‘‡Ū2_вÚ,û 35VvÂۛAXŧŠË§fĄķļx{âũ‰Ījv°&šÖsę›AĶqA\Iē/›63S%`aöCŊļĢļ œ*­LžđŠŖJ0ĶNø¨u2ĨĻĒX*,ĶEuODYƒKÜę]LčsIĻX€  ķ7dLŨ§ģT‰Đ.Ú°Y'ÎÔM]į¸+­¸n#°tz4+‰ķ’ú›ĘXe„ŌĖJkë§Y 3>ĒŽHļį"t> aˇ“_Eŋ3¯ÂTލ9Ā&îĘĶ î–[âÄēo­Í8kŽ'ØR‰áoÖūĩûߑ–ŊņDûņS׊#•if)ÉLEœ ^7[1ukĢÚ­+_Vyۃ|ã‰Z=ȟˆwa?Ž#ģáoU™g†ËËË%ÂŪđPŋH¨9ú ŅA‚öÕOÍ Š vbõ3f–Té)¸-Ŋņ[3q¨9n ŌŨŸ<~t˛ĢĮWš\#G&"aŧŖ% íÂR$Š2H/Kŋö¤h“ĩØlŠp“jy¨9.G3É5Įá,nyÛ+×G¸8´ø}˛…~oĄļšã¯‚”#°ô|ú i)IB#ųåĻ\ĒŗwIJÚíúąi͎ĖėĐ# 9GIĶQü€­Įrv~ŠÍälģžÁŌĪzÉ\ŠqŲ­ 9.ŽÍžélHÃjÔfÍ6ō`J¯t¤ž*î#JĨî´õ,”éXv3ĸäåOWū˜îތg:ĸj¤ŋ!ãL{=ĖÕ&DVÅz†qJ^U´¸ĸņĄæģecgc¨9âįÌmĪHÛZŗ•ãņ¨›ēAčRi,G‹ Ҍ&ĢâߏBN ŖÔŨŒÆgß2—k\ŠžTŦIÆS´!˛7ŖQaÜĻOŦãČ/Ŧrølr¤ú)V<YW*ST?%Õ"•ŠL]ĮKyÛ.cŨ ×5EöTŽĮų՛unåxKČ1āžšįŒeîį8K‹ÄM5ÖnūšcĮÆ]SŽĀYŖĮwĢŸqQžY-Ķb'MŲ"ÎÔJĮŠ:MDLĖfĮüĩĖpd6så˜ßĪŅY˛t×@õw5G`û8Ũ-ËÕėȆę%âjíũ”W›Ŗ2;´:vąĪ^ZnĘņŅsĢ÷øîz{ū(īōŨåžß%ÜäXČCvļ  Ķ!B’# a%Īōlĸ@“-¤ŽœÎԐÖT¯ŲÆD{ KŌ,'ĶôŲijxE)†UgmQ)Ég=Ķę˜÷\ ~[rĐą‘į!Č|Ä&ƒŲQ]ρ˛¸Ŗl‡ė*’+÷o‰D~I˛ ¤É~ˇZۃ›ja´‰QsÖĮ,åH\ôARŠÉÅ?ØāBÜŦgĐ3;spj K¯ráĐS9ÆeGgNũŌ˯ôYZ~âs¯%Î —:-Ta,Ņ˙~Žũqâ1}åšŊî‰p(ķŲԀĸeBXZ9uRLe`leî™V ŠZ“ N¤3…™ ›´•‘k…bKŠšcĶCĨ8hĘē,š"Į¤ÍË"Ņ`¨hķqĖ–h¤nŪ¯+y æŦJr$s@›`č/U‘¤ËZ2i[ųr­ĖyCÚ`$Ą)?É.­&ԌqHõ´7z!yZͲļÄqǍėMŽ8[ đ¯Ũ™ÚėH/,õ˜ęáH­ÆĸÆėáH­ÆŧēŦ4v1!ˆEįŽ<Û.Ѝŗ #.rŧ(pĄĘã’ß­.Ōaą-œ? ēąZ+érođFrô°•d6‡žta=$Â’C9åŌĖÁ%š×9žf‡,ŪÔüq.°gƘŗ.pv âCÎtyBáRIč2HŊé$ƒNÖ6՜wæ Y×9žlÅri5˜ņÜ12]LˆŌČ|tNĢģķcđ_Ę™T鄃T;˜ŧ2‘Rkåđ48¨–aÆÕÉü˜qË˛ŲÆ~*Ŧ2VįëƒĻŦ2ö3]•q2ĸÖĨqį ß˜Åä8U=âņĨ—_Y` íPžŊĩ­VáââbŅK”æäÔÁIŽT3.˛›[ÁUŠ°Ã¸›2¤ņ8“­Õ>'ßuˆsSsÜ-°Õ]=‹Ž5Į #'Æ'gėÚļ°ÎhĢ'ÆLf ˝­ŽâS}ŧV`6(Į..sÆhęĮãŠëģōĖ U5žŽrŦÂÖŽ¸V”ãÖļēĖgÆĐųÆųūøã –•)åĢŌ¤™•VŠ#J̰¨čbŅÅO—Öəũg'Ÿ´ņhO~JŪ€_9.DŽNŲœ;ē0cXë2 <Ø}ǁōēOIėv‚Š?D—Ø<Åĸ#9îŗé¸Ú~ŧ#črōÚKޤNQā?øú1 éžxÖ§°jEVY’9ŠtŌ…íføž$r8*Į^‘5šÉĸoÍ1>ƒKynJž‹G6z)˛fmōUgMū­Ąú:ƒĒYŋĸdgͨ˜uÖ=’Đc`n;Æę5G}Čq.+‡p‘7āt%kęĸBŊdY”Ū”øĻ"+'ú#kŽš@ÎväVĐļ¨ ō ärļ€ŲO¤¤įņāƒLĄC•8æą§ņ žŧ×Qx*~ĨbcÚ¤)Ö0XŦ+žųéļ„Č1ÓĮÖŪÂ]D9’Ņŋķ˛Ûtœ-ŽB…ŌÁŦĮ—VŸžŠš$ŒäøQ6_ÁMebĢÔ•hÜęŪbŊĖK\įxÖ¸#w´•°ĘnÃęf5™4ŗt&ī~ųéĪÖuKA|ÆÔÒdŗŦæHžhĩ–TųZF@91Öē–ŗ5­vPšžüZcĸŖĸyĩÔXî!–xė'Ö2Va 縊WŌĩdž[Af5GŋžÕˇjj¤ÕĀų é[~YÃ˜ĘžƒŅ˜ĄÔQœ™M‚JN-mWI]KƒƒJm ŲuŽšËūeš™PƒŖ^9úT[l_m/īX{Ũ%ņĨ:žČļghÂmŸ_…}Áŗ"9f5GîõēVŠĸÅRįr@ÍØž+ĨøÔ!Ų×:ēøÅ†’ŒMá)ĨŊĖ|DÆŽ$Ų—ÜĈ_’žÔ\{–ųΟĄC9ĮŦKyjŌk1‚›ímĄlą9/‚3”3õˆ@Įû9ΉĀîĒÍ+ČØ*ɑ˜’,̍ÅsØøÕĨ ĩĀrd-™ujOfT-ŠÄ…¤ŋ:yŧÎą-kfÕ_ŖŌärļ€>_ĖŠ ’˜ÎzĸC\åG쐖l}­’]Ôf.ZK”WĘqįãScQšžØœVŖæĸŧŧ\"ėũõ‹„ønuqØŗ6yĻĮ†*hÎ %ĩéA‡MEŠOzøTbĨÁ0c­T…¨9ŪHw“|ōøŅÉŽN_å:đSÜxĸĒpļÖ~ēËÖŨRՏyߒĶlƒČqk¸›ˇÔ­!G%8õ ~Ėøk…æBä0¨”ŠÉL[˛\kã‘]&ũ¤ãŲĶÉxwņČäl]•Ŗ‡M‡íZĄ¯Jč5đdÄķ <<č ĘZƒũnĩ3[īĮ,Psļ€~äčŅqÍN Øf ëG]`š‰ĸn ĪļĨ%“FģÖ%w•ã3ĪŪÔË^{õ.æ†ˇĶ]ž§›ÚzF°Îcúâ4Õą˙,ë3ŗâËė›VOœ¸'Jđãš#~>ĖØöŒ´­å&GS÷͙53e5VÂēôārŗ”ÔĘĀ™"Q,yČŧ–ė…÷–,Ps$ôz‚ *Į›#ĶA|ĸ۔YRTĻHrĪîZ ĸôņ ķŊ錇+GŪÆ€Ž‹(…?"jŽĀĐé1 Q3UäōbĻ,Z45&ãĨ =yĒ‚Iãބ…ʧ…ōePU9žá˕ŸÅ76Ё3Ãɘ1xɑ„ōÚOã<ĨęyqԜŽvĶ>ĢMÉÕ¤[OĢíÜYĐNNĘ+×ĩK‡Ųæ¯~†ā˛gVwđ T…t’cøŠëSy•jŽĀ–AŅįf¸BvUc9Ō†娘*wā8ÄĸE›ËBTŌÅtC‡<áÆÔ hāV´ĩ$—Šz(īĻæž“%dNĘēŪŦ¯9V“Ŗ â-Kvå`uŲô ™Jû*ŗ ĨØ{\œe/Å^÷ĸJĒt!Įs˙Ŧ‹'~ėâˇ'ΞG?r€fĖx4ĢOÁьĨ¤ŧ8cVvąˇ’™Æ‡ĩGæđ–U?;~pį6Ūí\–;y­ŌōPsÜuŽYayįņúŠ(ąČEāUĸĪiV%ņúšU‰>§šÍœJĐo6Zŗ*yč4ƒr<;•Č” /*ŧbĮ˜e2ʜÎbķzĨ xq„<™Ū œ÷ĸ›—¯ņŖāåüár69’6"q\NU!e΋¯DTI‚.[šķJēԋ¯˛”Ų}d'Øė¯Ā}TŪÃ1ĢĻ^‡ë^“âđũč9ãH!ĨZž†˜kÉnÁbˇ˜"3žÍ)2ŖļĢ‘!$Ôj˛īœæÜuFãųb­ëąWÁŦû9ōƒW–Ė˜gU1›¤XõGY„LĩE¨ˆ+Á›Tą(đ…b„(XĒ3Ē7Øqė`v\@ö90y11v?ŽŒĘą,G˛Jö0li’-2î8>ŨĄælõäHĶ/vÆT¤SBōir‘#+bĐhåËl˛œEc4]!-Ëė›MŊÅ"y× eeĐS+ôxA͑ÄN>Eé¯ĒS”ļI™ĸĸ;Å,ōMeŠâŠ([mÔĻŌRãNš*ž4ŊͧĸqÉĪžJ …75ĮlĘYOTĻŦ:ã)kŽŨTuãļG˙ČŲ1ãDR1[•ĖĩÜČŌčTs$ß$å†üT!'íŠLfŠvVId§rŗ‚Xų)ŽÔ(NĨfƔ$ņ”)A Ō” ã)C!*ķL”#„îwå'¨ÖŦph`Fž ™é¤Â6ZŒÛ&E’ƒCDUq[13ųņēæČfÍA`ŊŒ9—Ú˚ČØú(GšmFŽļ͌z˜‘ÕvšQ'3RÛN3ęgĻü8Ͳ73ČØúߕ'ĄÛdĩËPĻKŲ.ÕÛĻ´Í¸ÃÅĶŽ¯"”Ú”V'6ĩˇķëBQ‡6ÜĪq“¸Swē K߲lb]ē­¤ÉKˇĮî ÚCČĮWųáå¸Ič¸}āÉq˙OÄ]ûWâŽášŊŅsŖ‡>{ĀĀ“ã]û'ØđŲ6‚ŋ!pž909090HNČ\^^ŽŊ€Õp˙ÁÃé”āSŲÄÚ{ØrÄU#Ps`r`r`r`r`r`r`°Ũ›ŨĀÉp§ž īƒbr€îČ×Þ<~„÷Áķ>#LĀ7ÄFā}š###Ô 'žyöšŠũÚĢ=ņ¸Ü7āZ`ßĸøÕm䕂 ˛Ŗz#ųĻ`žEÛy͐VĀRØČA~FØ3(G8ĻDr<ōG ã\2ļaGn76Ōä'@YMËeÅmƒ5¸ģ#,ŽøÄ…ėJåxGũ“°:@ް,2 čwÜMœ ›âGœ€ĨĐ&ũJ¯;%!§jėę€r€nČėQyŽöØĻôڈ’Zî-bmVÕ Gč éh—ēSģtTŧÎĩoŅZ@Z ĀäĀäĀäĀ'dāĪ}ķīđ>L9Ā]ypŠ ŧ1@Ž€§Ļ\īC Ô€€€€€€Žs|ņÅ×ŪĀļ@÷îŨ[{›Ã˙˙0ą”v„UIENDŽB`‚smooth-0.9.11~git20260403.0230c0da/doc/reference/screenshots/messagebox.png000066400000000000000000000074571516402577000257030ustar00rootroot00000000000000‰PNG  IHDRėŠ&1*tEXtCreation TimeSa 9 Mrz 2002 23:17:06 +0100e&FtIMEŌ a+[Ë pHYsÃÃĮo¨dgAMAą üaˆIDATxÚíilÕĀß{žoĮqŒĮ8‡›ģ„¤nܐ@G Zũ(!´¤đĨM+Z´"Ĩ‘*¤R$Š”R)BĄAFA@Č}–&$ÎA¯¯ĩŊ÷œ}3ko6{Œ×ŗ—Ÿ÷˙Ķz=ûf<;īío˙ūŋ™73ԉ#_ –G6ū‚ÅŋÚ.Ī÷–€ļlŲ‚ŸŲđ‹“G÷å{{@'ld â1@ÛˇmíččOŗŅ3lŗ7P xRy˙ O jėēēHLáxŠæŽ.’`ĩ‰×ĩTĒkˆzÛDkĐÚ°Dkˆ{WÍ ‹ZCTņToU­ ĶlÕkÛ$­ŠÔč|Ŗ ]ØôW8æ‹o§¸¤Ŧ>tŗáąÍ¯īsĮ—ƒÄ@ˆ¤§y!i:1úÕK#˙ũŖö÷~ÁučųžCĄfÉækš…ˆvĐ՞/kæ;v05œH— mÎī€Ä@ēüūíĶšOĪU‰ˇoÛúÜ# ųn ä¨g Sž…ŌŠ™ŒĢįw4迚tĸĢĢ+ßÛ)ņČŲÍlˌ|oLšk$ÆiqžˇR":āB$ˆį‰á*‰Ā;€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x@b€x2y+A”M[€r;,v#sõîĨ2%Ę($ĶŖ^˙Ĩŗ_™О˙īŠ͇ŒIėAeU åH–hÆ`4šh†‰Ė•â9ޞČŌÖÔéãĨūkO]1]^jĪwõé@$ĻĖ%gIKĢM–)Ņ–eĮõũĪŪũîAĪ-ëŋm3[ŒFŖ Ą'(ųū;׎rōŽw÷,nvdŧJ1—ɏ\v<æbˇÚWoNņåÚYƒöģGopü °âW5aíĸo@4ŠZgœdUË,iI,Ë2gĒŦ+˛š-lH ,ŗ!ęĒ…ĢīzjīÎŊ8íĻgÔúΞf6XąFZDh4(Q˛p˙]ßûč́Áķ-ŦR˛Ī/ábúæjcį„ëIŅŋČËk7u˜Tkč#­Žl¯¯)2P ˘í6Ģ…Ž2øËcį÷î<‚ęnFĩwH—ėOŊø!.äÕY8J;Í4N9†kVĖk˜ãĮ.æ¨EsK˛°šú-UŌ'_ī›KôGâ ą˛Ę,#Æbļ:í&.á%ċˆĸ‘…Aĩ5åČ\‹ĘĢoģˇķŋWļ67⑁EN˛)Ūjr û¯Ģq\l\°˙ČĄÅ i:ģ{KbîkĸqĶŋ o 8Ų{­MAĻ=žDIr›č暰YbĶČRA§Ä~d/5#™6™Ŧ§Í¨”H”M!ID ÕW؟Ųūđö7/12ûĐ}s~|g›OD8'–d Ą Š,¨ØLsĸÉí ­^Ö˛íđ‰ĸnלëj˛ú™Åˇ”vķiĖMö_2|ģ”˜e"åŅΝ]Âōdīß1•¯{˛å#īžŦa5Z,#9†‰e˙EIvæb‡ —xBŠ8 ã×yƙÃĶŽĀ BfTŸũ’$eĻ„EË‹Ę¨ŌÆxŦg4pķ-¯ŊüjYŠŖŦ$[ģ,6VäØė\ sj×.ÅoH|1ē˛ņuOeĩņˤŌ‘o—žæŌ#ąO4ÚÍĸĖØĖf+~9Œ Vīø%Ģŋ $¨ģÕp’åîņŦ‘ÅŗDYųā.Ä ÷ ē9œFW¯ˇžĒÔ'šëî\y=Ë2:ļJ71A%•šÉö-¤ķFš¯`’č%Æc”Ú8—čÉAŊ˛EÂŊ9Öh4ŗ^ ‚b…đļ“FŊc‹nyfņŋmXúĶēÆģ˙úúĮvŗē˜„8IąĮlžGũ^ÄÅG†ŊˇßsÛÁß ûrY˙HHøÁhĪÕX!YD’čĘę¨ģîvˆ„|}īĨ'ķÁ@ĐĖØQ•ū%)_l0-)klh˜Õã;-œĸ'bQ†”āĘˊĮJ0FJđÆŋüAÄÍPŖžP‘Íxæ|ī…oĒĘswŠ‹ē^aėv{UM}q‰Æ2N'œ)Ŗ›ōōúõēĐ-#Ģš.˙ō7kŸxh™Ë=–QHĒĮXdül2#¯‡sģqžņŖ>ņ“ûVŨš~QúrIžö[ŋšëƒŽŽ.];ŠâYd^D‚¨Ū',1~ˆ‰hȧxŧ`vŅ…“—‘Õ†ĩˆFęŪ Iq]Tw(‡Ķh%Á᜗ F’¤ ūZ$›ŖqŠ GbŦ/Ĩŧ(ãtB`4–$Œ=?Rķ Epü#¨y0öXXD"¨ņxŒÃ3^ŽdYžÂ÷¯Žeęė ×ĩw" "Ή8‚†#kDUQ¯­¤ŋŠÜōØ1<ŧ˜¨>dUe<‹FãI…ˆ8ė¯${8AžĘ7aĻ*ē:v´‘ qŖ>¯ŅéTsÅUe?ąšNȊžJoOXŊ $RįâpĢx,¨ #eW1žĀ tCŸ_āøžaNVŽ–ĀṸɥgåë Š‚ĮëņøD5 ķjHÆâŠjâ ē*rXbA=b'„Vķ ü‡Øl¯?đûpÆüņî=Ī›Õ#ؐ:z"qmŨĮ8‚~ī {ˆ6*CؔŦX5˜Rw>ātBRÜŠUĻh>,w8u–ÆŌž“<##A.āö‹‡¨¯.ĒĢ.Îw›„Ą'W•9z.^ŽŽ¸ûz}AĨŗ&¨û€yĩ‹†3 ƄX†UJ9aŸ?`˛(œąÄ\xŸ…Bœäîëâ%ęĶĪ÷]8?ŋuæĖÚŌ,U5f§&‰G%€„č5vC“ņë^_ čw÷ģú]=>Å•Âû((åșsžS§ûPEĨĩŧˆŠŽ{÷ũ'˙7Šg)1˜V– „äĄū~÷đ@ ž<ÛûÁŽ45Vĩˇ5”Û˛T՘ņ(Ā´A§ÄģĨŪ0:dp>;Đ×īęŊ22ĮWģŊŗûČM 6õēJ暚g͚3{ūbÉÖ~ë}¯ėŲ{†5+};74āęęįųĐÅÁĐÛ¯ŋeeĨ—ĩ´ˇÎČņĀ ` <ņŌÖĒ÷?īž`¨l( ö_ņx}6GąÕQˉ–%‹[˙ōáķåUÎ`į•g¨ļÎŌ×ŋ‰ÁĄĄĐđđpĀ7 ø(Y>{yäŊī ]>ˇnU{į ­e8[)~ĖJ˛ą…hōÅŖËSn›ƒášNZ§'Ũŧĸq÷'§ö÷9Z[ę-žAŋ×Ë 2ƒÕæ(//6PœÉFË,4̌õąBC#ƒŊ!čÙŗO ŽŸēđáŽįYšāû ggô$% RLŦ1€Pû‚˛<<ˆ'-‰)ŠZģ˛Å~¸ģëŖŽ’æļ†J§YāpfÜ7āĻ._f(Úl29‹ËĨĄP`¸ŋ— xCĸqį/ģ?û÷žžsįĒJmß]ŲŪš˛ĩõēęĖ&ņfÄŖ}ĸ¨ŽwŒYy6†įņ¤{ļŗÁĀŽ^6ģļ˛č“}_}r4 MM3jëkh a)ƒ>oˆįkEÉ]ŧÔwüČI—k°ûĐ—Õ•%Ģ—5ß°¤yÉüYõSlˇšîáÂņ%$Ī%ŽĖ\wĸšą˛ĻŌyēÛuđøųîîSįNííą;‹:núŽŲjįDÉb6ûũÜ[¯Ŋŧ2ŗžâ֛–ĖoŠ_0ˇ~Fm‰ÅlĖl•ĸ]ÉË8ôč1géŪH'4ČØÅSlVķˇÚfΙU>PwągđĨW>ú´k˙Ŋۃ;wÎĸ"ą˜äāēuKW-Ÿ[W]R^bËËÁšT4Ō1:;7ÃsAå„čOœ"ØãÍ[wŽøÁķZ›Ę+jûz÷ËĪ?|ĪĘĩĢÛ˛}V3é€Ŧ)ĸ°ęŗƒgÎÖ]ßPWFQ0bČ$šƒķ‡UËZV-ËwuéäĻņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€ÄņäčģŠ@WWWž7!wlxls6.ˆ35) ‰‘úŅæ{rÁöm[ķŊ 9Ĩ°$ÆN|* 'ˆ$ˆ$ˆ$Î0ķÚWDŅ… §ŒPpģŦs]áøË ŇŗDâÜg 8G€ÁŲ$ˆ$Î:nf¤Hœ;Āã,įđ8Ā.ļLãhž\^î9Ŋ‰3L2q'\Đ ¤ņ€Äņ€Äņ€ÄņVĮŽĐÎÛ) Hâ9ÁŽ) ‰áėēé äÄņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ€Äņ(C1ˇlŲ’īÍũPųŪH‹˙ą]žžb$´õIENDŽB`‚smooth-0.9.11~git20260403.0230c0da/doc/reference/screenshots/popupmenu.png000066400000000000000000000017501516402577000255640ustar00rootroot00000000000000‰PNG  IHDRdy@ČF*tEXtCreation TimeSa 9 Mrz 2002 23:05:00 +0100Í|ÛtIMEŌ 6ėœĀ pHYsÃÃĮo¨dgAMAą üaAIDATxÚíMŽÔ0F͍o3HÃnXö}X°ä ŗœÅÜ'K؁÷ĄĨˆ¨Ļl§ũMÛŽ*ķ=!ä„ô<Ų5Nų§Oŋ~_HŦo ”@Y”pVĮOÖˇä…×—įËå"ĪœĶ‹ūüúa}ŸNa3 ,Ęh,ëã§Ī‡Ņi_ŗ&$a3h/ëúfž­\ד۟ũ°TpËųūQÃUÄžŪåXti†ŲĘĨjÖ~˛TŌĢfĨ ‚Ö&‰A€ß$n67ƒ˛ė™Ž1KV.Uļ~ęwŌX–!SGĮ˙ꐖ˛Jq:„ˆZƚFJ öā( €˛(  }?KūNœ,ä7–Ĩ:â!úåõ°ŒKŅėe™Ģ‘gdÂg}$kyëHŊ9īå´āŠq˛RŌ×#‡‚$–˛œĢIqā˙ĶLŠJĒn„<1ÃÕž–žü8ŸĩDHo1Ÿ0(Ÿ5‡/> ”@Yų˜ĩŽĢõYōåëˇė\ŅséjëöH^įāfaĖ ,Ęč8`1G¯]ŌqĀÂgļķ:6ÃÉL-ÃbViöíōvn:Ō“ŲüTŠm†hŋ“ęųÕ5Ų1k71`QiÄgm’ô]ģsĀÁ¤[ˇUlDĖĒ™ébübЀEÍIˇŽvēXøWP'āđE€˛( €˛˜Ī`> €ų,€ŅpĶ)ŖrŠŧæāã‹XáXV§|Viōîā–#ŸUúxėšUzÔ{ōYŲ›,̙ΒKŌGHúG€|VvדR˙ßÃãg…lŦëz{;W¸Z…á]–Ģž-_¤( €˛(  }ŠFĒđ=iĶwÜPŲŠyĄņ ›!ĀYûŦ+õwv––gm‚Q ^rs6kˇˇ8ŊÆ!ŒY”āBV”­J™Ī*Ō7ŸÅųY3yÉâ"fE˛( € Ę3pAy¸ €1 €˛( ĀlÜ(yw‰Ų¸žˇØ,Áf0nAš*ú"§ûšÅf8'Ŋdj\õô’uđ]t֏ü~í€+§ĖĒ õÆM Q…Ō`ĩgēXĒ87á€ģ”@Y:fŊž<[ߒ_NĶG冰PePĀ_I:õž!ŧëIENDŽB`‚smooth-0.9.11~git20260403.0230c0da/doc/reference/signals-and-slots.png000066400000000000000000000173531516402577000245440ustar00rootroot00000000000000‰PNG  IHDR&ØčØ4ĘPLTE˙˙˙îî™RULAD: "vwsģģģĖĖĖwww03* ŨŨŨBD=*3^w4y™C”ģRÉ˙oŧîhQf- 7D!lˆ<†ĒJ+3CD? ¯Ũa df_"CU%"13.ˆˆˆEU)13,ĄĖY "$-!#)3efc ``` ?@< uvr^_\ #01-AS$  =M" "+8F"ĒĒĒ(38GL`* ĄÍZAR$:D(6D9D& a{6Œ˛N.1+8D# —ĀTVn0w—B"*bd^AR%  XZS5CMb+ 3A 470QSNAC?BT%  !"   deb "" 0=   -8-0(7F[s3 ¤H l‰<!  @B<#+2;$.;)3"$+6E!>A99H ORJ )+7222DDD=@7H[($qqqMPG#%XXX@@@gƒ:%,ŠŠŠhƒ:,4 ŖŖŖ #-&,'2SUO.:c #,&'%¯¯¯îõîU—UfĸfwŦw"x"ĖāĖDDXp1i…;3ƒ3™Á™333ģÖ숎ˆnŨëŨƒ§I"""&)" !”””888 %/'1777ĒËĒ (4C 000&. /9#fff.0*bf[----9UUU3ANPJ"& VWT    [t3 (((!:=6 (3@‡ˆ„ ŅēˋIDATxÚí]‹ŸĮ]ßŨžGģëSŧģZŲ–ČɎÅj‰)7¤ĮĒå=DîRŸNR°ą)Ø $ČųB“Č>”^JSQ^-!MBíøQbšvAE%Ō0ÉåßF+Jļyí”Ęß öcS&yâ(ęäíÔ=ÁĻKŧ7kéžoš“‡2^$“Ü;Ūy/Å žū†¯^iū[ŋíƒĪo%šÂ}õOXžÅą1ctC§­đ›(ÖøOa—ŋVũŽCõÃ8ąLJ@›<@(|"p™ąqžŊ!I’â&øŊņhH,Ãmz¯äSđ÷OMÆđö) ˜äĀ´6ųū†-Tnī– Š:b˛ Ŋ€1q#@Ĩ˛Į|dæ(E> Lîoj3Ã+ŗÚîāŽ‚ˇ!mĨđāģžģ–r”dwųw$?¤M>ēŽ#É#MM›Æ>öOäũņŽHīųžī­¤ŲWÉėô/y*ōO„†‰L´É“ØüũŊ ßÅ<¸įûÄ´N—bwŠŦã§´éĶ\Š`‚Kpß?!÷ Ūû?xāL*͏¸3Č+`F›:ËĻ&ÚAķ øŊī+„š#?úC?üØãbúŦĪ–`ƒoNiÚėūÁäčáoHagPŠø‘}œIŲa{°/ܧiMMLĻAhQíŊĮŦ‡Ōģžœk΂3ŠŌ(™€Ã*%hu´Ų3遉͌°×”tn^kΞ­¤&[ƒNøxj Š6=09Ž“Qû1|Scd…7˙ū§SŖPX{(ߏåˇēĢU:E˙ —˜< &Âx`”T$cĩ%õÂōš9M›!<ք‘ø÷åŧÃdāaņ<ō  ?ā4S OŒžŦņ Lļˇ8tt4ZĒęĖ”žœAâ;œ’Îqeįšđč~a–8Lė‡qÂDÜbL Ā^B@mÎđéCˆ§)Žp›3úfˡ `Ã)‚…œš Ŧĸ'ÕĐPs XŌˆšĻũ¸_Ģ#¸b:Lŧƒ3b˜¸9ufÆ”Ę %éĶ=[HN9 HRĢUt]䔆‘ÄHĒ VPU[ ˆÁ…ĀŌ'RŅ3[ \Đ_Z‡ē†đ"ŋ &HúuŋCjËgīŋėâTĒ™cÉŊŠ đ#Ę’ÜōVm”í¤2R3'āÄčT‡ÕéÅĀDlŦT zũ}.˜ß]ļāDŦĢ ŒÅ×=ÃA˜Ŧ N&ˆ+y&eX)’yg0‹°žÉ€kØŗ"* uϐͭ&Åž(›Î–“´%™œ”3ëMúÍ2:)ˆØ¯Ö+hôWœX]u!šã&ŗô—üÕ Â7û™Ž(Ŧp:0š`…níD˛ûÎ@á`bõˆycį$’ō‹ĨXT͇Fūŗ}ĄKMr’QŽ…8Q]ŅĩŌũM%ķRĐĶɂ ķl¤r ŒwDŋ&ë‚́IÅ9å†ė$BVn4œā›E˜8ņ5&ŗ'Ė„¤‘l]Ŧžë”ĨLîOL˜7ø|y*Đ,Ū%údģ9…tÛŨ!pR€-@m]pPrߌ‰’°SģĸōaŽ|ĒúėõûšĀĻe";Ī`ī “Tˆ’Ŋ㏠%3ŸH…2ajgÖŽÉ|˜ĻišoqōĘDp~ Ĩ–å×)O}ŌB‰6ûtJfœl ļĻęåŖF¨ųXja˛´4ЎĩžVÂΘÖįL˙ZŨô_gfSŗYBfg0-ĒۜpĶ×ŌFØ;vĻŖü觚ĪAŸũ•éĶŗĨF6Đ&yyŖŸ3vZRbÎUvė‘CäÔÂķf÷î×ãĶLj(ȖE–2™ ĩø%˜\ŧ´´ôęE——Ž\Ŋv }šzeéÚEãéĨ‹Ãu +nšã3ŋČö¨…GÔu¯ä=Î8€˜uâŋļŽĘD{°’>˜\[‚ôš„ëč]č˙–^5Ÿ^a’˛•.eŲ/PĐNŨŸš2]×ŖÎhQz–ueļų|ņœĄLÂM…pã 7L â¸xe醄K— ˜ŧĘ|vé&suéæ­[ƍĩ8Ä.Ēܡfļ€rÁû>d%ˆ‘Ī=d âhÚoũļ…’m|žŲguŠOՍם ˇkHTÛāĖ­€É æę[:n.]eLTÜŌĄqëōuæâ˜ÔĞYģĖī€÷ä=ėpR-äŸ/ÕŒhķŗāw͌8&EÄû4;§>ŠáP&Œ˜%*ĐV›—n@ĐÁ0pqëōĩ›k¤Ōļ-E×l^ŋ÷ûĀ–Ĩĸ˛–b))EŠüyÎ×įg\™|ėĀūlÖČčŌĩ‹RfŠ-1_{6äDAC{6LŽ"/Ä4:Ģ`ō„Ą5aÂvm˜¸2áí ūäOī7ųbŖ!}FBÔh|ņ‘ûxũüķõy—ŅæŽÎsߊĘįĪ@;][ėķˆ–M%ŽÍëW#€IšžrúĪÕĪ^[ēb‹.?Ž,]wáfN_[¨|€??ô‘Ôë§ūĸnĐTŗéƇĻ5§ę ĀĶK}ԐRbģ“Ž ŧXčë_õ˜ÉĄ;s¯HQ؜š˜\^ēyú#7MöŗĖĢn˜ 5s}ˆobá¤ŗ†kË[āÅŋoŠ7›Íi ĶđËŅúäė‹,Ģ X˜D úaģŸ&˜xØ˛Qĸ ?Áo'ŋš=įԄÉÕ%.ë@ø‚ņŁÉk7VČčc=ŌīĖōGŗø¸{"į㋋ĮÄ ŋZgTŒNŽzО;ėßŪáÅHį,”=€áũn'îĖ@sŜĶëW––Ž\ļÂk7o^wÃäęĩĨ›—¯_ģžLDūUũđ÷F]\RaMŨ —*ÓąV ŒPāĮŸ´Lî–šy a;õ%Ë ]75zpĮŽWht8vw–‡ģäCLŌhâŌcCo9ū÷Ŗm€|˙Ą%xēü• ˛^ŦtdfĜĶ̆+rÅ JēēqRŪÁ~zŠrO (ūaÔHšrüˆep°ĄÄĪҁ:Ãöüumf­ T¯™~Ї6dļyĄ7<}ķ;¯éŠtrúéü§!gŊŸ{Čn˜õÃøÂ‡ģ ę“üëķv—tÍQʋ¯ŪÔũ”uĮŊÆÚ{ž18fFā};m)Û˛īŸīĮå•HŠJOŊî€dföaœŅà Ô-Ž:žZúĸÁ m/ũ‘ŠÕŊņíž0"Į銴Õūå_?>/cÅŠ8Ÿ‡œVŠM>÷j˙ö^'ū•ōā”+H>ÆåÚ^Æč:afínē"÷ė1pęßëį?gžōųį­)yF8qööņ*|”e_ EQ¤—Á—ĻŨaĐúbpĀĻîĄ Y'ZŌɁIÚöæO×uĪh+h~öđ~osrrŽ~ūu€ž|~j÷éĮO˜ÎŽęÜŦė˙Į~´L+YĻĪĨ (OƒŲŠé™Ģŋqv?ČgØLiĢéāÉāÜ-{kįąÂ3ũĶŅj¤îāƒlå đFŊŪ4ëož~đąŗ'j¤JĢŧN#IõĀ!cŽŋrÁÎč䝡ī¯Ŧ¤8)œhP,ž {ÄĮ™gĻ ĸ$øYbŲhg̞Ũ.=žr$Nę“ÉŗAÕ Ëp>ë uēE­Ũϧk¤ũ >C$sÁÃ<œ˙Jk‡ķ/„ÃÕ(Fĩ¤¯|b ?HĻ'ƒŸ5Áļũ[ąŌ8 ;V›—¸ĮÁsSM|ƧŲŦ?NƒķŒÃP ÛĄîÉēMI\<‹1|ōÄ .¸Čû†7ŗbhhąL™"%-ÔAøÂ7@íNJ¨m` .c8ȝ&z ”NU‚3€ŌĻ %ŪtāyW<–‘ĒNNė˛|ũŒ`ēÉZõPJbØõß|cĘŲāh$˛,#†lĀ|ŸĨ`ką PZĪ+é$Œ#ļ(N’F8j˛Ë=ŦFrDGxĨKφÁex>aŽGŲ$Y<ũŠJ oë2í…ÁŽpBgz@/ú˛”á–`[ŸÉuđûÁËTĄ$‚x|sôøēžy SŨ­\šč. sQ›—„6ŅČ+gÁ܇ŋēt‰šŧt“%@(įĖ‹Sæĸ6/‰dí´uē=žĸzüžēã+rī. Q›S—°ŒŗY ™¤9arøĄĮ¨âÜģKÂ_Ôæ´8îYHDēV¸~øĄĮX:ôŽ5Šî’(LR“e{͉ÁCŅÉļ8ëÎm<’ˆĩɈƒŽKēiÖŨĒC/CßgŨeģœQÖ@IDŠÚ\Tæ,$˛=ČŦŪ 8ôX/cIwŽ\Įæ,3Ŧ~âõ@IdŠÚTÄvÍîҤŽ8ôiŦëzËĮĖ0íÎ@I„ŠÚ<§očÉö ÛŅ­û­LNAÁIŧëčú ԃLۉ×I78čd#&’$Ë×ĸėēŅMņQÅĸ-’=H.Ō9Ģ,Ëtčļ˜:m÷„FÂ=H>â}—8čZ/,‡NŠuŠ’ փL߉׉tKV-Ú"܃¸¨[ˇĐîRG6t¸$â…•Ņ¯ĐKá‰×IIôû ‰ŨČ× SĄk3BPw“,žMã‰×IōībØÔ›Ŗ7lŋO×–ËÄāÛĩãiØôÄëĀ'–ÕŲũN, Đã‚´.FØ\ģī ÃSÅw/1.ߟ­×AOŧöMņíÂc8j–ē'‘P6ÎŨ…:blEŖĄpŠĪ zͰgé‰×Ū‰qj_AŒ1$ʉ K{<^¨ÆÆ;ųOŒw›4ļÛĻž¤Ģ¤M–š˜aBՉ—ná&ŸųĮōôÄëuu ĮÄ>ųĸŌš9Î×Ŗ´ē†’0TډũXrtdí2Ė Pˇ1>ä&ucYîMc[.ːcō0Ž‡­cûjņķŲHqū6°M**ÕRĨß>žņ§—ųŊ8yČ)ŠœŸߗ[‡ bŸ„Û'¤R7wîōá6ĘCŌ#!y5G‚”=w˛ąķp÷ŲØyØvgúįægļË9B¤ŪĩCˆ‡|ŠxH0J&Ē9r”ß‘ÉS%‡$[’ԁ8ŲËR<ō\ĘJ'§ŪŊ;vrwŋ’v§&ģī",\iŨĩÚģw’įO î ƒiņäōo‹ŸéĢ ÃWĶĢLōÄĨ›ŅÛŲ¸yPSĀC‚iG‘ŧxrīxįŊlė<ü×ŊŲ„ķāũö¤“+Ü÷܁áū‰ ō}“ į!Á$–ŖO hõáōQđ BÎÆĖÃh9$&RâɁimō6fæ´É'ĀÃ)ôOÆĸĪũMM{đXŧ<|ō0{"r8‘B˜#Ī#P<ĶÃÂc2å!é0Q"6y2~ę‹ āái “♍Ĩ~˜ŧ&úûyÊFō°!`âC>Ģ“™âyv$Lˇe<ŒÎ9į3Ép˜<›Z˜ā”9˜„iË~`b—@u4Đt{ŠĘÕ\2(‹ `Ąšs%Q˔Uģt=iĻÎÁ… ōŅĶū÷€|<„h[“ đeōčU ĩTG Š~ŖäJ‚žō L õ6.LËG˙ū?ōņ2mŲLt⠟+€V.ŗ‚2(8Oōđõ÷ŗ’TĄPJn]†ūJ†<”œōAƒō Œm9 LJÆÅ¨æä†ä~|Rm9 ŅÉ ē:CžčĨIÖ*˜äAĄ Ęškt‚ËĮŦH—|Ãc[& ¨ņZåUAšņMa˛Z>úĮ€|Œm9Ƈ[>8`ļ-ûI9ČČĻĪ Ā‚ė8ŅČíą’\pÛLã&EŌĖo8˜`‘‘Ö-ŋ0!Ņ–ũ¤ Wl4ܨ‡]ōFU¯uW—\vūĻ%É Ų.]O }k o8˜`‘‘Ö-0!Ķ–=ņ@bš4P7 LHËĮLČ´åx`ĸ:‘z “õäWKvc5ĀéS˜Ŧ#Ÿ¸`âÆj\0i¨&åLÜXOŖQ˜āQ˜4Ôô¤Ō`Ml}ü˜ĮÃÉėdkgëëØÂ “TņPŅûjm3L†dëë$aâdKa˛xĐ+Ž}ķJ=ĄĶA_„č@eĀ.Cãa*tm:hŨwRęŋĩp°"ÛZ s;PÈŲP˜¤&`8X]tĄ˙CĩŒj,Oõ뮑Úēī¤Dŋí90qgËë(kÂĝÍH˜PE”ĢēÛÆšc¨>—aÍ/0éC˙ĸͰvŗÆ ]q°=c-‰}ßN sZfúLŗíÃG"cūÂÎf4LĸÛ°axEˇqEĸyÚ¨m#‹€Ē° ÆDEVŋ“9†u`Â3¯īĐeߡS:ŋ]mOÔĩabg3’2‘m˙2\õ%S:C7lȂ"åa•§‚\Ž^R`ÂT&ČząŌ‘K Signals and Slots
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

Signals and Slots

Signals and slots are used for communication between objects. The signal/slot mechanism is a core technology of smooth and probably the part that differs most from other toolkits. smooth is probably the only object oriented toolkit that supports signals and slots without the need of an additional preprocessor.

In GUI programming we often want a change in one widget to be notified to another widget. More generally, we want objects of any kind to be able to communicate with one another. For example if we were parsing an XML file we might want to notify a list view that we're using to represent the XML file's structure whenever we encounter a new tag.

Older toolkits and older versions of smooth achieve this kind of communication using callbacks. A callback is a pointer to a function, so if you want a processing function to notify you about some event you pass a pointer to another function (the callback) to the processing function. The processing function then calls the callback when appropriate. Callbacks have two fundamental flaws. Firstly they are not type safe. We can never be certain that the processing function will call the callback with the correct arguments. Secondly the callback is strongly coupled to the processing function since the processing function must know which callback to call.

Old-fashioned callbacks impair component programming

In smooth we have an alternative to the callback technique. We use signals and slots. A signal is emitted when a particular event occurs. smooth's widgets have many pre-defined signals, but we can always subclass to add our own. A slot is a function that is called in reponse to a particular signal. smooth's widgets have many pre-defined slots, but it is common practice to add your own slots so that you can handle the signals that you are interested in.

Signals and Slots facilitate true type-safe component programming

The signals and slots mechanism is type safe: the signature of a signal must match the signature of the receiving slot. (In fact a slot taking zero arguments can be connected to any signal because it can ignore extra arguments.) Since the signatures are compatible, the compiler can help us detect type mismatches. Signals and slots are loosely coupled: a class which emits a signal neither knows nor cares which slots receive the signal. smooth's signals and slots mechanism ensures that if you connect a signal to a slot, the slot will be called with the signal's parameters at the right time. Signals and slots can take up to eight arguments of any type (extending smooth for using signals with more arguments is easy, though). They are completely typesafe: no more callback core dumps!

smooth continues to support callbacks, though, but it implements them in a typesafe manner. There are some cases where callbacks are more useful than signals. If you want to be sure that only one function is connected to an event or you want to receive a return value from a function, you probably want to use callbacks rather than signals.

All classes in smooth can contain signals and slots. Signals are emitted by objects when they change their state in a way that may be interesting to the outside world. This is all the object does to communicate. It does not know or care whether anything is receiving the signals it emits. This is true information encapsulation, and ensures that the object can be used as a software component.

Slots can be used for receiving signals, but they are normal member functions. A slot does not know if it has any signals connected to it. Again, the object does not know about the communication mechanism and can be used as a true software component.

You can connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you desire. It is even possible to connect a signal directly to another signal. (This will emit the second signal immediately whenever the first is emitted.)

Together, signals and slots make up a powerful component programming mechanism.

A Small Example

A minimal C++ class declaration might read:

    class Foo
    {
        public:
            Foo();
            int value() const { return val; }
            void setValue( int );
        private:
            int val;
    };

A small smooth class might read:

    class Foo
    {
        public:
            Foo();
            int value() const { return val; }
        slots:
            void setValue( int );
        signals:
            Signal1<int> valueChanged;
        private:
            int val;
    };

This class has the same internal state, and public methods to access the state, but in addition it has support for component programming using signals and slots: this class can tell the outside world that its state has changed by emitting a signal, valueChanged(), and it has a slot which other objects may send signals to.

Slots are implemented by the application programmer. Here is a possible implementation of Foo::setValue():

    void Foo::setValue( int v )
    {
        if ( v != val ) {
            val = v;
            valueChanged.Emit(v);
        }
    }

The line valueChanged.Emit(v) emits the signal valueChanged from the object. As you can see, you emit a signal by using signal.Emit(arguments).

Here is one way to connect two of these objects together:

    Foo a, b;
    a.valueChanged.Connect(&Foo::setValue, &b);
    b.setValue( 11 ); // a == undefined  b == 11
    a.setValue( 79 ); // a == 79         b == 79
    b.value();        

Calling a.setValue(79) will make a emit a valueChanged() signal, which b will receive in its setValue() slot, i.e. b.setValue(79) is called. b will then, in turn, emit the same valueChanged() signal, but since no slot has been connected to b's valueChanged() signal, nothing happens (the signal disappears).

Note that the setValue() function sets the value and emits the signal only if v != val. This prevents infinite looping in the case of cyclic connections (e.g. if b.valueChanged() were connected to a.setValue()).

This example illustrates that objects can work together without knowing each other, as long as there is someone around to set up a connection between them initially.

Signals

Signals are emitted by an object when its internal state has changed in some way that might be interesting to the object's client or owner.

A list box, for example, emits both onHighlightEntry and onActivate signals. Most objects will probably only be interested in onActivate but some may want to know about which item in the list box is currently highlighted. If the signal is interesting to two different objects you just connect the signal to slots in both objects.

When a signal is emitted, the slots connected to it are executed immediately, just like a normal function call. The signal/slot mechanism is totally independent of any GUI event loop. The Emit() will return when all slots have returned.

If several slots are connected to one signal, the slots will be executed one after the other, in an arbitrary order, when the signal is emitted.

Signals can never have return types (i.e. Emit() never returns a value).

Slots

A slot is called when a signal connected to it is emitted. Slots are normal C++ functions and can be called normally; signals can be connected to any function in smooth, even normal C functions.

Since slots are normal member functions, they have access rights like ordinary member functions.

You can also define slots to be virtual, which we have found quite useful in practice.

The signals and slots mechanism is efficient, but not quite as fast as "real" callbacks. Signals and slots are slightly slower because of the increased flexibility they provide, although the difference for real applications is insignificant. In general, emitting a signal that is connected to some slots, is approximately ten times slower than calling the receivers directly, with non-virtual function calls. This is the overhead required to locate the connection object, to iterate over all connections and to marshall any parameters in a generic fashion. While ten non-virtual function calls may sound like a lot, it's much less overhead than any 'new' or 'delete' operation, for example. As soon as you perform a string, vector or list operation that behind the scene requires 'new' or 'delete', the signals and slots overhead is only responsible for a very small proportion of the complete function call costs. The same is true whenever you do a system call in a slot - or indirectly call more than ten functions. The simplicity and flexibility of the signals and slots mechanism is well worth the overhead, which your users won't even notice.


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/doc/reference/smoothlogo.png000066400000000000000000000176061516402577000233750ustar00rootroot00000000000000‰PNG  IHDRĒ`ÃéĄĮ*tEXtCreation TimeSa 9 Mrz 2002 14:32:35 +0100e dtIMEŌ ( …ͧƒ pHYs  ŌŨ~ügAMAą üaßIDATxÚė xTÕŲĮį.ŗo˛'„$$b%€‚hĄ( R jĢ|Z÷ĪĮĩĸV‹Õ¯EĢmՊˆUYęJQve“­@Yš…„ldĪėÛ]ŋ3 RdæŪsīĖ$™ķ{æáæžuîũß÷=Ë{°Ė÷~T DėGģü!ˆÉˆQü!ˆÉˆQü!ˆÉˆQü!ˆÉˆQČhW@ôJģVXWŊ%6Uƛģp!Úuŋ˛ūDŒ‚ä@Ä(HūDŒ‚ä@Ä(hęč}8v~Áyĸ’¨úŅ íŠ÷,ü!ŊĮÎ/Ųöķĸ’Æ!ųģ äü"ˆÉˆQü!ˆÉˆQü!ˆÉˆQü!ˆÉˆQü!ˆÉˆQü!ˆÉˆQPČxžgmÍtc%cmäÜ6žĄŽk„9A™”ĨLÎÄĨŒÅq”n8K7WŗŽ6žō(@a=nė§ė—ĻLˆëŒŅîKkë÷2íįYkëjįŧ.Ūįâ96đNāj=Ž5Æ~„9‰ŒOĮ5ēhW6 æŦŊ%ĐGį˛s”‡§ŧ_ļ`* a°āĻ2>0Åc2&dƒŖŧtĶ9ĻĨ–uļsø)8IčŒčí„ eJ6FČ ]a?ž7ēŦ™uĨ鍕I­ĩ ífGĢÁc×yœ*ʧdéĀ% ĨŌPJĩ[grę-vS|›%Ĩ9ĄcRf]ZŽÍœņŪÖ2†ō–{Žn÷•ūĀښēģ Sk5š#u×ܤ><íĐÅ1öĪ‘­žãģ¨Ē’€Âv]nmÁúÂÉĒô<†EĄ[8–n¨ô•ûĢJ¨ē3L{ø¯ĐÉ0ŒˆKVõŦÎŽÉ ū"Ë -Öeõ•ôŸ=ė¯>Ūpõ.DkÔzeZŽz@&ˇP;’Đ›ŖŨŽ^ U_æĪ×é}T]Šĸķ­Ų%¤J5L7lŧŽp2D öļĮ2ßûQ–zk|îa§÷ ?ŊopÅáäÖ:č|€2ڍņ•™å¯)Í-<—‘ĪÂ>m+˙ęÚûĩ¨$„9ą˙kß^ų˙Šqî[åÜŊ’ĩ6 Ī ×›7Üiúå,\gŅėĘŋ4jkFūąO…¯¸KÛĮSįŽˇ¯z‹Ē9%%`0ļ,{ŅtĶoãĻ>äįÖYđüķRŪ",r ëËî˙+iIGˇøĢOZ×/đ— GæĐÛ­Ëį´ĖxZ=h´_#Îë´o˙ÔšëKŪī Kū‡cû'Î}́ ›&ĖÂÕ=}Ŧ3ÂĐÍ5āųōŪßáõI€Ąė›ú*~L|āMB/ÂĶ‚’?žOoŦŧīßo Ž<ąž"8vXiqvíé'""œßcßŧČąëKŠ~P',ãØēē=Ŋą Ž”R}*otiΈڴŧ–„t‡ÁâŅ,J×ipÛã-É-ui•Yĩg˛kNj{Ø Ú7 +Y{+aNž¸Ŋö͋ ×ũ`¤J“ŊļāUF>Ÿ؂ÂÖ3-5ūęŪãģ|g*8¨Ė9ÖūŨRMŪĩĸ–4:w¯”2•¯LÍŅ]=Q3B™”Eûa¤’Ŗ|Ŧĩ‘Ē/÷•{Jvr.+\Ξ3ûÁSj¸vtŨŨÁļŸgZj•ÉYAŽ %ƒs¯×_;Œ´ĢĪUŧbŋ6€LÎJ|đMUjNđËpŪ<å!unaë˛?°â§Čé† `?ĮAÔ°WTO?ęV]á$đFÄpâĘ X—Õĩ­}ËRh;#`7đĶƒė› !Ā'%Å{@{Ž›.Vû.ÃęŌ­¸íŲÕĶ{hĶ­Û?MiЁĪMxœsĀ,¤C™ !Ļ>R›ĪA”ę–)ØĨŌ÷ųĨ9+?žû•6a¯z‰€gø2ŠXa;3ˆö]„ŒKJ˜õ ĩ•¤˛üú…”ž0ŒžUHtÂįL ŗVøâŽöģ}+đâŸŖLÉąüę ÚwĄHP@eÚ ˆâ@%9Ęō2_ŲA˜Ûn™ņ”*-WT"íāëLīéZ$˙šãą3lēéžôW֚ožO Üƒ_!áæ* b nû “ŋ!25:aÆt3ká­Ą.Ú@*÷Œ-zéĨ•ŸßūÜÆ›ī“1į.ēCgw°áģˆ2uîę‰eĻĶ/~ŌOŧ´ŦŨ°ņeą‚G`XÁŦ.ÆpĶM÷Ũ Æ~QŧŽ|ŸāPõĨ!MTžį=GˇAŦ­Ķ Š6At'€įåÆ;ƒ6uSQÎsl‡Ā}ZŊķ”ÅFcĶæÕ䎄(‹u…: !ÔôÜÕ'÷æËŊFÚ§1l™0kĶÍ÷˛­t0‚€“?˜˛pBwÍM 9Á3'ūŠÃî›2e vč/āĨ2VŦā}n_¨=HÉŲ:˜ _ b¸Z ‘Đ› cfB$ô—Ãt{ė 1ÂŦæũîāĄ´BČĨa]DÉŌŗ?zæöšŖŊY*2¨Ōcb F)(“ŗ1čPĻw˜ōˇ];lž÷Sįŧ÷Č´mËŗĪ XÁqÛ{˜ZCDdhR8aG'j ‹(8w`Mčæ+ÕÚü1RĘÕƒ‰č„nŽ žāÎ_}bå„:{.!Ž8Ųą Ft2†’¸ŖšoŖLĘ ĮQ0!rlLʔ’;ÁqC*ƒø;EĒkĶU÷\“žW›–[—šë g@öH‚JQ§yH*KŠÂÅ[a]VFü_ ũĘÄRĘ%ŌÉ~Š´€Mš—ÔÖÖ,Ļ ŽԌŧFZˆiV“;"8X ļŖĻB—ÛˇÁH%¸ÍdĪBū€T1 ąöåJTŒ?§úøtūxäíqÉõŠ9 ˆsCĒ\ÕÚÕōēŪAF.Ž9NŠš]kk†X_MZ’qX/áB› Â"Zūxŋ'pŪ^z×Į\`ĩŖø˛Š‚š‰ū9Ēūƒ;ļ6‰[ĪČ´Ôō,ĶCŽģ끐æÄH˟_­-xÍUâW>‡ŧ^ãmMā3üô>EįoĻ„3š…§.šęúöŽV˙öX0 ØØx<0¨Y!0PGô‘Ā1‘vÄ-HŧߙũbŌ­uŨÍPp.'~20ÆK7䉸$L­;•ÁÚ[yʇõ—HvpCœôL.#„üņ l˙¨ŠáŋËđæhsx øp Ŧ"{øž13Š §øĄ&ā" pxÄ/ŨR\˜2flĸ' ë/UzŅd?˜Û}…'Ŧ‹&€ë͘ä[×[p•†)œÛĒGō× ¸NūŖ“CŊ´1ėĀČ)VS¸ÆÚģŠŸWuėĄ/_{{îôiۖĢz~H œ€š‡8Úa+ në>!Íķínļuu;[Ęų=<z]ôåÕĐčĨ˙”¸Ö1@Áy|ߝ”N8În íŗPJÍĒiGĨÁ&—õÎõ ^˙۝r:‘ōHĖ(+lÖᇠŦ€Éą[ nđ4ČnPžĄ Â)í“>úP\t&ĶOÚ˙ž FĘ˙ÖđĐbØŪëĻË­f'ĩnáĶ37/¸̞Âû`ö–˲Y.“`Ëš "`xÆ0BęņęĀķÅ Šņ,’ŋn ‡ƒ%Čfáq|ŅŊ¯ž‡XÍ$Į}ģčž¯ßDÁÁ„\uŲ\†¸ˇ{ŋ>YB‰åų‰˙YuëöOĸUŅĮ1bÕÖ/õõg–)¸1juåšĸ͋ž;­ ôy0 Ԝ‡U ?šúįāęî]fRĨ?ŠĮŗ0#†W´…æÅÔœ;ņ.3B âėŨzķüGŪYz×ËNŊükp„ Ļ}w­{ˇX͎€›O!X&P!-ƒč5F*!&1:ā¤Ë1‰˜u‰äō)„XųStŒîēūļ_^ŊnĘÃn¨ØsÖ_Ai¸Žˆq öę+:‚éK/šsÛ!R‰¤b°œ÷y¤@XsÈ^‚k Ōg]ĸ€\ŽĖĀÕĶ›ũęĻ%wŊ\:đ.lK1ŽDÉŌcmŽXq1—‘J–ƒ€!ÂÄ+:ļw÷Ž5B„Ąe=véž<įq@øō¸!.|Û]"i‰“_­Û}ũmģĮ™mÃOũeC*~´@D-˜ĄĨÅCŗ"$#DA&d@¤ĸ›Ē3ōŌ^ûíģ­0P`O‰uA s§BڞKÖŲq<aJˆØÖID'r띯0ģ)aΘ™āƒxkcvÍŠõeũĪW¤6W'ĩÖĘ1áįčŧδĻĒÚôŧ¨tYæÂfU‘.ckdŨ6Ęqî„Ŗ|´øŨė ĒAĖU\Ĩ%-Šôųrq™24ŨXŠJ—õ€iށđ Áģ9ŋFîđÖÖ/|ũ”g™”–šŒúōĖēŌŦÚSĢe8Ė˜~‰mõHūd‡0đ–ąG\˛Ö&Ļĩ^ŠüŽdmh˜„‚íˇSe öžÜ-6[ßŲÃú‘S ÛČ!Tęnj;DJĄĄáH‰åÕ÷{tŽ Χ ŸâŽ[ ãØueĨÅŖJžX}î§ 8Î*Š?\o!“2ÅĘOy}å‡ÔYCĄËõUã\ĸįO”I„1˜æĒ3‡N9 ë¯*a]˜…\ÛĀ:Úü§ņ‘Jõ€|¸ÂQŪĀ’ M.˙—Sųe‹6”u¸b—đ8Q= ͤû_}vųÜį?ŠĘ€ųÉ1¯”<=‡¸ Į5yŖ!zJvĀ­\Qt<–îC› jžRD™20'ŠÍ–n¨ ęJáÚđžÜˊœŖJÍ%Œa,²hĶÔe„’ŋōƒˇm^ôĮų˙{gÅyĮqv÷noo÷¸W÷÷„C@@Ԉ„Q‰Šƒ[ĢÖÚ12š:5ÚI›Éؘ3ͤuLĻØ6$Ŗ“Ä´Į—Z“&‡„4jŒĸP@AåMî¸÷—ŨísP3Imåöš7āžĪė0üąĪžŨŨwŋįå÷]ķÁ>Ō_A`؍„Ŧ×ļÖ„'MüÄü›Ā>¨PJ+€đzako€;Ŗ­ŖŅŪĶ"´F1TúüīC¨į¸+ …ãŒįŽđN˜i؜Íd<{b^Ē$ŊĀߕūÜ2§ãĖn<‚cË?9øŌžõēȝø˙Ã(S5ëSā0Ü, PqųPCGBdaŦËP÷6kÜΤ7|ŧ?LøĪ’Œ}H4•†anc<áŊ] ‚ŗB2ž;æčî-‡átîAŊrSdœwēy¨Š>ŗOc(Ėmy~ķšŋl{ļvGz÷7ž:=aZđÜi–Ēd-jā$Å”A4tÜŧb8õ† Šu<ëԟzÃŅ×q:Ļ`š'vĖ AŠcuß+t0ÚÖuŅP÷DčG&Îɯ &~/œeÜækûؙްˆ`NÛųßūq틝>YÔø‘Øët˜`ÉÂ ŽœbÉ@tJ SH!Õ-AYĪûāOœgß ŪåПŦ5û;ĉ@ˆ*õlíšHIį-…8…k´øĀ¯ˇ¯{¸ŋũFķČÁŧÕq.Ų‚JĄõžāÆŲĮΆîĸ•Āô LímŨúˇkv•Uú]VûĒOg]Ģ>۟Ņ}YhÃŪ¸‡Ė°Ž˛ˆ))´˛ĸU0-yÎøŲ{Cĩ;ėŊ­îe˛2|ā7ãPą@öhĨČãđė 16‘-Ö<喌 :gˇęÖngĄ&ü‹į¤Ņ9‹„ļ"Ô0Žžũ?˙ W]bVâÕÄÆj\ôå?Āf‘ĘÚŌ ÛŌ :“sûbŌXŅ;&x^fÖį^=ŋôķCÉÂÃō—ûšÍrd…+Í  3‰ũúÅ;¯UI’sÁ¯Z’”-ŌÆãā]…aœÕäîĘhm9cëj‚¨E:‰(2‰ųÁžī/ŽL-Xåîag1ŒÛdšžWJĨĪĮ¤ōtķNģK?äč´v4X.×s^Ŧz–—n$„ąžĀxæ°s°Gšr™ ģß  ĆöîoŦWŋ0}š3ÅŊ\į'ƒi‹oæũŅVSAķg`˙ģŅPDܰ:F¯ĐZ¤áļɚ|˜ÔfĻėfĩ~0j¸O;ڏÎÁëåPé ÂsšFQöÔČģ/@–_į9{÷%°ųūĘpBYļE$0š /Ygiū—ā ÷` CÆĪÍįwCeŅķ–@4G§`b \u[Gݎ‘&†Œ×Ēh\BķŦ‹Õ:: ŲĨ‚û~0Ng]1ƒ=1=[=„~§o°ĘS<”ą3…šņÃ`_Č÷`ō—ŅšĨB[2•ĒbĮđÛĪC,Åõ8¸ĒĘgpÆXŽŒÍĀi9\ē=‰ktÆyv1ÃfĪŨHĐ}úØÚ`_EH€‰HUÅ3âé´˛äžĒĘj¸˛(ŌĖ"fúĪ%J08ĄūŅŗB|ŋ…`’Ôŧ`ßÌg&É߸LšÃngĀ,%CGül7UË÷ŖĐj6ė†ÄpƒaŠŌLáĘ`ßĮP,ßâ’öBŽ™üåa¨D‚wĖųŗRĖë›^š4ŗ‘Đ$YÚĒ?ā5zž<\ąé‰wE0ąDũãįči0nâPÅŌM^:j‚xÖËĘ4ˆ™!&ZžoËŪļŒG‚}!Ąˆ$9'rË^ÂģxŪ@("ĩ›÷PžČõpŠÖüdSX>1}+`˜|i•˛ü˜ČÛĘϘ˜T”ũÜöĄÃt—?>,ėVtĘËÕŽ"í ’¤ė¨§kÉDøš.А YQÛkŠ”yž: [×ŋ Xž9,āår1‰TŊv§O´o:ĢXöhEФ|æã÷‚WŪĀâDũÂÕĮžØnķ…‘6Âđ QOŋŽ?ųĻ{Iŋ•mđâđâÕĘōm>ąQ˙.@}€‘I9cGīē ŅOql†fũ.I‚Χw‚)+Ē]†Qks}`îb–1…ü}Zŧü-ųō}”4|֞–¸˛úFbVŸâģR˙đWLŪãcīר}ˇîûB&į¨*ĒŠ”\˙ÕŌY Ф÷ uoĪå}[Íčûā´\ūxUxÉZO) >¸DąņĨąãJĶ…aÂŨ5Cœ)äĪ Đ/ßvbÅÖŦö†G.Õåĩž 7ûˇÎ(ˆø.ëŠO/ūiûTåŒAÃ$É9Q;Ū´ļ¯{gĸާoKȁãgËKŸ”f{92ā 8#W­úeøck õ57~äķY¸LžpuxÉ:ŋŽĀIŠfŨNiæ‚ą5ŽQ˔ÅŖo‡-ē"°a›ÚĶ:ˇũBfgSjoĢØw‹YīNĖnĘ]ܘˇė.Ēæ2ŊÂDĪ-‘ꊡÚÍM§,—ëŊ7{#”QtîbϰœŒøūÅX~E¤‰ÕŦy^šbĢåŌ'拧ŨšîŨʐ\S…tAŗÎ:Yø)1:w •Ydūę¤ņėį@—¯_Kŗ,qŒ/@ė°%ŨjOíi‰īīŒģ}=r¤bw >œ1…ļNjoÜÃ]ÉŲ×RōPƒ ΎNÛĩ¯=Í@ŨŽž2Ā0B-‰Ī$“˛ŠôB26=áž'°ã#ļkMļîKŽ›WŨ5ō<ˋ1JFƤ‘ YTZž$-ŸâÂ$žwÜî˛^ųÂÖõĩãæĘāQhÅŅŠdl™ “¤äēÍįĻĪDq?/˙ Ī3–q•aHi‘Y RĢIėtHm&ėŪ[ČFŌ’2Ķá&F5ĻԎ¨į8 –û Ļ9œŨęígõCŦé.g5ņ6?LáNÉpŠ™ ˆõDš˜EF^ޜ5 ģFXã(g2pˡ.„Á$R‚QŠBKČÕZ=Ä5>âég CœYĪšMÜīŠ9ø8H)FR¸TF0*\!RĮøŖwr:ã;ųC ˆÅt|_!D@ō‡@ B$"DAō‡@ B$"DAō‡@ B$"Dų7Ŧ.„f&ZNIENDŽB`‚smooth-0.9.11~git20260403.0230c0da/doc/reference/smoothlogo_small.png000066400000000000000000000053721516402577000245620ustar00rootroot00000000000000‰PNG  IHDRŽ K‰×Á*tEXtCreation TimeSa 9 Mrz 2002 14:32:35 +0100e dtIMEŌ 5r4ī pHYs đ đBŦ4˜gAMAą üa SIDATxÚí[ PTįß÷vßŪ' ‚€(  (Fĸĸ(*[Oâ¨UGŖ­#ŠŠ5™˜6cĒIÆÚ˜Ú´j3IM5NB4M=Š÷EPP•ÛXØ–Ŋ÷ũÖÅŨ÷ž]v Ļüfgxû˙÷˙ūĮwüžī-HėžÖ ĐįíĀ ‚Å`Š 8Īہ˙˜ËΙJNĶ%’Ŧåüã‚ˇ0XĒ~‚CũĐ\z†.Ž™Ū# ƒĨzvXkoęōwŌ%âI‹¤3_éŖæKõė mfGË}ē„čÔõ]sƒ´bĀ`°Tũ4R$ë[(‡# Eß:E´ĢI›…- a‹d=˛OZŒ„QGá8ʰĨJ„Ãíą‡Eš:HS;ø‹ōÅN#(ģ’Ķ{G+i1ĄB [Š ˆˇŽīRÉÛ['Ü*HŽ)‰jŠ“4<ģ•DPŗPĸ•G4Fލ[ž”Ą ĸ?b,>iš}.‘ÎZËI˧Ŗā€šėe3=#ÜØŲėĩtūƒwh įž4Ÿ$;ĩ]n…ĮIgŦgä Hˇã„gĢŊi,:f­žjėšĸXÄÁ¨LqÆËĶIFHÂ\vŪTrŌV{‹4wĐÃåF' ĮĖLÁģßt^η֔ $7—_Āĩé’ĐÕ;ļŋņāĐ>6œ9d.= zI—ûĨhÂ<ųKëP˜Ž‰@K|ĢiéņŊ͝ũ‹Cāū"dąNN[~dÉ[n‰ūØ^Ù/č:aë>˛5V?XžLIįüL1/—"IvûwĄlfoҤ劭>ģŪŪĒ=üĩâšŋ:°9Ō™Ģäs7t—,[CĨ6o›ŖŠÖ D Qäü Œî†&oģŠč8+Äė.D0įīøĪ&ũ–ō•÷ Ŋēũô~n÷~ŖŠ ˙å_9ŌP„‘>ƒöí}šC[ęzŧ–Ķû /hüŽ4ęģģk8ũ9mēU`Ŋ{Ĩ;Ķ÷G#'ˆÆĪäŽļzõŪ Œ‘än(8čhŽ [ģ á`ĐMKUQÛū7(ģÕŋ ĘŌŠ;üŽi”Ī˙…ĪNķĖĐũØO~đÖGÚŧ÷Uūėn”6ŊPTîĄw‚ŠSđ㇠گļųŠ“ †ķy°YģĨm˙›ëô–;—ôĮ÷AB‡æqہˇÖÉãFÁA0?÷Vf‚Ėĩâ*}Ä{FUÂũŌ”šbēĒNvdŅϊ„tƒD‰’„ĸŖuXCå˜{W^,=+´š‚ņJŠYEØp˜ËÎųtÉŖNøķ¤‘ą5ą7VF=[ŦđdíüߥŨ Â*r6 ͞Á䎷ÕÎ}e,Ÿņåœî˛ąiŲ˙œ—Ģ ÚSW.?°Æķsd’€čÃĘ‹ŸV*3ŽŽRi‡gčÔŦšn&ŠgXÚũŨu_Ųøĸŋ­ø-h‹ŽŽÉ%§>Øĩ2ū~̇đŗŸĨ+ųšéÍ؜ †O3^ u?K9Ŧ•Šû!(„ƒE’=ēųņ{ČÂČŨ­1YŋßøiЍ˜=Įaë;ŋ}ÅĮ\w„›rØŊžíLJ÷ĀĨė>Ąŧ ÃÆX}6ûL%Ģã_Øúë¯GÖŪwįrüÃÛC›ę6ßŧŸî‘d­ Ÿ*(m˛V_§h›kBßĸ9°ÅOģŠœÍŽS%70U,Â2Ū ŽļĪ69_8ņ„¸Ž‰Eā1ģ Yhī,oūf^Í<¤­,H2¯:ĩK•ŸŽŪA=:„rǟ˙1˜ŨtWŠĶ 6BB,thØĢģ,Ø’tÎ:øpĪé g.FKŅËë–'×zi(ÄžŒíō¤IīŊqHíuēŅoĀT1›ŋāœ@I_ZļöCī7 ‚¤‰á›öcv&¨@˛r›|nŽĪ7 ōą¨Äū‰Ú3^Č\Ršš5ŽübJõ¸Gw•ú”vĒA ¨ZS‘~-}níđą>Ō/L›ÅH”>"ÂĸŧtB!nT"Ŧ#Qúđ[Žzm`nĻëĮÁTÆā{ގª§J2^æ(#ũHʐ-‡ÍegM%§ß#ÍZ\^t˛`ėLņ¤…ėîØ"YÄæƒ—ōMÅ'ÍĩôS(°Ã"YhWąđap\ŠČ˜6!Ū°TĪŨîūŊ€ã°K:žķ›˛ņ„%áĢoū@đCømā`ę asĀXDŊŪ}‰ ū'Č@ÁāË ū üTQŨ  ŠIENDŽB`‚smooth-0.9.11~git20260403.0230c0da/doc/reference/tutorial/000077500000000000000000000000001516402577000223265ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/doc/reference/tutorial/t01.html000066400000000000000000000035461516402577000236300ustar00rootroot00000000000000 smooth Tutorial - Chapter 1: Hello, World!
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

smooth Tutorial - Chapter 1: Hello, World!

Screenshot of tutorial one

This first program is a simple hello-world example. It contains only the bare minimum you need to get a smooth application up and running. The picture above is a snapshot of this program.


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/doc/reference/tutorial/t01.png000066400000000000000000000034271516402577000234460ustar00rootroot00000000000000‰PNG  IHDRČdLäč\*tEXtCreation TimeDo 5 Dez 2002 11:10:24 +0100¯ĸvĐtIMEŌ  |j pHYsÃÃĮo¨dgAMAą üapIDATxÚíëoU‡Īšũf/1Ņx#A„Ļ!¸!Fš”kŠĨ\ä"˛ĨĨˆ”P*.´D.Š”€Ĩ7[`ÁrIŌ´ˆF”Ŗņ1øE*žĶiĪžŲnˇķît‡ß“ååôœŲ9gwžžķîîlĮsũģf€­ä,[åĨ˙Rpz$Ā=Š^ũ‡Ök-N¸ ¯,aŪŊ¤Ŧ´Äįķée¯Úpoŋ§Ņų‚čŦO¨5ŧ-´ŊŧŸÚ*Dh#ĨR(÷5wļŊ0 ĀX§vl@GŅĐ]įvÂ4ãŽÍÆķéųņ„IvĶ–wâíũ.@äž[ŸĮq¯˙:n=ŸWPŲŌnއXŽEĻ;ŽāäRxã‹ÂļsĢųö˙偅į?Y@…sûæŸŨ÷VÜûŠŨ<­Ļdj⟟¤&Ņ3ÖOŪ§øÂĢ&˛Ķ×ėדͨīRŋ5ƒâôu3V֛rSĐ X īvęƒgĖ•ĶŌĮꅁCR)ĒΘk"b%֝ļRŊđĐĀ|Š˙|ŋÕŧÍcà ôÂ͖M˛ōé´5záˇKëde_@–<ŋf@פÕzļs54ŽÄŧ˙o‚īĘōđŠÛ)6×åĒŒĖ,Ŗxąr‰Z9zÎ^õGZ )ŽYx€âéōš˛~ŧŋB/ߙ%+§ä×ČrŨGĶgŧWGK!•3 ŽPŦÚ4Yļf xpŨĩ¯ųëO A‘ItĶMŠŅ*a‘cŨšąƒâ)yo_ß&ë˛B/<:t%Å[W5ūēRLņ‰ÔÕOĻRá&Mšß/¯§øė¨ĩĪZK…Ÿ×ʝ–c5)8U`ÆKé[†MŪúōdmWŽ,“õi;ĶfîĸÂåjŋŦ|%{ov9.\ņAŲ;—â¸ÅßxįʲõúIK+ĶsĢŌķĒŠ|tÛLšŊžJĒ‹§PĖZœU¤BÅú‰jëŧĀIŠû‹^ˇņ¸&šŸÔ›ĄU*ģUÂbÆę7 —ÜúˇĩôÁ”eÎ#eĖF‹ŊĢ3–ŊŒ_rHķO„ĪXņ1īƒ†åpɅ>o‰˜­Ö¯ ûŊ¨MWí­Ûz<ß×Ŧ’3'vÍĸ(g,`FˇJ-tKÔK.…4iŅRøđ |§Í4ėžMq‚˙°ĶaĮ:=īuŽRķ-kĸÎX´R$ĢDWōnÁãÃWQŧŲŧņĪæ ĸ+yfdÅ_/~š¨Ĩízōūüh-§ä=–‡4tŌŠW-˙ú˜qMĩK›jrDWōŽķUÅâÆCo Sō.ģčSЧöĖ9ųąf•žŧOĖŅÜ îx3XšzŪ—×ŠŽä]Ŋ{æĒŖ+7Ļې.ē’w@æŠ7ĩɰĒ)ŧ5Ú4eđˆÖk-“âCč–zmĻä]ũ$ôR•öǐ’wÆYE2}}˙ß ‰yį´Šli×;ŊŨTN’šø°|oĻNßŅõbTÖnũ÷ÖéŅõüyŊßIoH>ą@,֖ČķąĖ‰UVZ˛9į)§ŸךÉOßxĐ6Ž"$–ŗgY—ļR2īôx@C‰üVŽ×Đāô؀K‹Ō,§Į’ubŒX _[vwŪ  °ą  °ą  °ą  °ą  °ą  °ą  °ą ö|ũ 'ËģõLöØąí{…8ûԕÄ}ļē_XÅ ¨@‚ °ą  °ą  °ą  °ą  °ą  °ą .Ëp ‹K*čM1^+ÆzŗnwbŪ GŊ'. 8Ċy™5C9ök¯š˜ģ÷Ō†ˆXˇÆ×E´Ëāē÷‹ņāŠķŠyŽąnŊ_ķN VŠ8ũ<،ûŊ6CôōXęĢaÄčô#î¸_ŦhĀVŧĮ?uŠS”-Ķ•›\ŋKg,õeųpFlíŠ7Ö]ĶKË8ēč˸\,ÃqRŒØd¸F­$Ú!ˇØĄEīŅzqUKaŒ¸é'ˆX€X€ˆX€X€ˆX€X€ˆX€X€ˆX€X€ˆX€X€ÛÎnˆû¯ WbXø“ÉĀ€=báī%Čą  °ą  °ą  °ą  °ą  °ą  °ą  ° 6œpŸĪįô€ ų|‘ ģú¸IENDŽB`‚smooth-0.9.11~git20260403.0230c0da/doc/reference/tutorial/tutorial.html000066400000000000000000000042741516402577000250660ustar00rootroot00000000000000 smooth Tutorial
Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

smooth Tutorial

This tutorial gives you an introduction to GUI programming using the smooth library. It doesn't cover everything: the emphasis is on teaching the programming philosophy of GUI programming, and smooth's features are introduced as needed. Some commonly used features are never used in this tutorial.

Chapter one starts with a simple hello-world and each subsequent chapter introduces one or a few more concepts.

If you're completely new to smooth, please read How to Learn smooth if you haven't already done so.

Tutorial chapters:
  1. Hello, World!


Copyright © 2002-2004 Robert Kauschsmooth homepage
smooth alpha documentation
smooth-0.9.11~git20260403.0230c0da/include/000077500000000000000000000000001516402577000174035ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/include/smooth-js/000077500000000000000000000000001516402577000213265ustar00rootroot00000000000000smooth-0.9.11~git20260403.0230c0da/include/smooth-js/v8.h000066400000000000000000006125371516402577000220520ustar00rootroot00000000000000// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** \mainpage V8 API Reference Guide * * V8 is Google's open source JavaScript engine. * * This set of documents provides reference material generated from the * V8 header file, include/v8.h. * * For other documentation see http://code.google.com/apis/v8/ */ #ifndef V8_H_ #define V8_H_ #include "v8stdint.h" // We reserve the V8_* prefix for macros defined in V8 public API and // assume there are no name conflicts with the embedder's code. #ifdef V8_OS_WIN // Setup for Windows DLL export/import. When building the V8 DLL the // BUILDING_V8_SHARED needs to be defined. When building a program which uses // the V8 DLL USING_V8_SHARED needs to be defined. When either building the V8 // static library or building a program which uses the V8 static library neither // BUILDING_V8_SHARED nor USING_V8_SHARED should be defined. #if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED) #error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\ build configuration to ensure that at most one of these is set #endif #ifdef BUILDING_V8_SHARED # define V8_EXPORT __declspec(dllexport) #elif USING_V8_SHARED # define V8_EXPORT __declspec(dllimport) #else # define V8_EXPORT #endif // BUILDING_V8_SHARED #else // V8_OS_WIN // Setup for Linux shared library export. #if V8_HAS_ATTRIBUTE_VISIBILITY && defined(V8_SHARED) # ifdef BUILDING_V8_SHARED # define V8_EXPORT __attribute__ ((visibility("default"))) # else # define V8_EXPORT # endif #else # define V8_EXPORT #endif #endif // V8_OS_WIN /** * The v8 JavaScript engine. */ namespace v8 { class AccessorSignature; class Array; class Boolean; class BooleanObject; class Context; class CpuProfiler; class Data; class Date; class DeclaredAccessorDescriptor; class External; class Function; class FunctionTemplate; class HeapProfiler; class ImplementationUtilities; class Int32; class Integer; class Isolate; class Number; class NumberObject; class Object; class ObjectOperationDescriptor; class ObjectTemplate; class Primitive; class RawOperationDescriptor; class Signature; class StackFrame; class StackTrace; class String; class StringObject; class Symbol; class SymbolObject; class Uint32; class Utils; class Value; template class Handle; template class Local; template class Eternal; template class NonCopyablePersistentTraits; template > class Persistent; template class WeakCallbackObject; class FunctionTemplate; class ObjectTemplate; class Data; template class PropertyCallbackInfo; class StackTrace; class StackFrame; class Isolate; class DeclaredAccessorDescriptor; class ObjectOperationDescriptor; class RawOperationDescriptor; class CallHandlerHelper; class EscapableHandleScope; namespace internal { class Arguments; class Heap; class HeapObject; class Isolate; class Object; template class CustomArguments; class PropertyCallbackArguments; class FunctionCallbackArguments; class GlobalHandles; } /** * General purpose unique identifier. */ class UniqueId { public: explicit UniqueId(intptr_t data) : data_(data) {} bool operator==(const UniqueId& other) const { return data_ == other.data_; } bool operator!=(const UniqueId& other) const { return data_ != other.data_; } bool operator<(const UniqueId& other) const { return data_ < other.data_; } private: intptr_t data_; }; // --- Handles --- #define TYPE_CHECK(T, S) \ while (false) { \ *(static_cast(0)) = static_cast(0); \ } /** * An object reference managed by the v8 garbage collector. * * All objects returned from v8 have to be tracked by the garbage * collector so that it knows that the objects are still alive. Also, * because the garbage collector may move objects, it is unsafe to * point directly to an object. Instead, all objects are stored in * handles which are known by the garbage collector and updated * whenever an object moves. Handles should always be passed by value * (except in cases like out-parameters) and they should never be * allocated on the heap. * * There are two types of handles: local and persistent handles. * Local handles are light-weight and transient and typically used in * local operations. They are managed by HandleScopes. Persistent * handles can be used when storing objects across several independent * operations and have to be explicitly deallocated when they're no * longer used. * * It is safe to extract the object stored in the handle by * dereferencing the handle (for instance, to extract the Object* from * a Handle); the value will still be governed by a handle * behind the scenes and the same rules apply to these values as to * their handles. */ template class Handle { public: /** * Creates an empty handle. */ V8_INLINE Handle() : val_(0) {} /** * Creates a handle for the contents of the specified handle. This * constructor allows you to pass handles as arguments by value and * to assign between handles. However, if you try to assign between * incompatible handles, for instance from a Handle to a * Handle it will cause a compile-time error. Assigning * between compatible handles, for instance assigning a * Handle to a variable declared as Handle, is legal * because String is a subclass of Value. */ template V8_INLINE Handle(Handle that) : val_(reinterpret_cast(*that)) { /** * This check fails when trying to convert between incompatible * handles. For example, converting from a Handle to a * Handle. */ TYPE_CHECK(T, S); } /** * Returns true if the handle is empty. */ V8_INLINE bool IsEmpty() const { return val_ == 0; } /** * Sets the handle to be empty. IsEmpty() will then return true. */ V8_INLINE void Clear() { val_ = 0; } V8_INLINE T* operator->() const { return val_; } V8_INLINE T* operator*() const { return val_; } /** * Checks whether two handles are the same. * Returns true if both are empty, or if the objects * to which they refer are identical. * The handles' references are not checked. */ template V8_INLINE bool operator==(const Handle& that) const { internal::Object** a = reinterpret_cast(**this); internal::Object** b = reinterpret_cast(*that); if (a == 0) return b == 0; if (b == 0) return false; return *a == *b; } template V8_INLINE bool operator==( const Persistent& that) const { internal::Object** a = reinterpret_cast(**this); internal::Object** b = reinterpret_cast(*that); if (a == 0) return b == 0; if (b == 0) return false; return *a == *b; } /** * Checks whether two handles are different. * Returns true if only one of the handles is empty, or if * the objects to which they refer are different. * The handles' references are not checked. */ template V8_INLINE bool operator!=(const Handle& that) const { return !operator==(that); } template V8_INLINE bool operator!=( const Persistent& that) const { return !operator==(that); } template V8_INLINE static Handle Cast(Handle that) { #ifdef V8_ENABLE_CHECKS // If we're going to perform the type check then we have to check // that the handle isn't empty before doing the checked cast. if (that.IsEmpty()) return Handle(); #endif return Handle(T::Cast(*that)); } template V8_INLINE Handle As() { return Handle::Cast(*this); } V8_INLINE static Handle New(Isolate* isolate, Handle that) { return New(isolate, that.val_); } V8_INLINE static Handle New(Isolate* isolate, const Persistent& that) { return New(isolate, that.val_); } #ifndef V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR private: #endif /** * Creates a new handle for the specified value. */ V8_INLINE explicit Handle(T* val) : val_(val) {} private: friend class Utils; template friend class Persistent; template friend class Local; template friend class FunctionCallbackInfo; template friend class PropertyCallbackInfo; template friend class internal::CustomArguments; friend Handle Undefined(Isolate* isolate); friend Handle Null(Isolate* isolate); friend Handle True(Isolate* isolate); friend Handle False(Isolate* isolate); friend class Context; friend class HandleScope; V8_INLINE static Handle New(Isolate* isolate, T* that); T* val_; }; /** * A light-weight stack-allocated object handle. All operations * that return objects from within v8 return them in local handles. They * are created within HandleScopes, and all local handles allocated within a * handle scope are destroyed when the handle scope is destroyed. Hence it * is not necessary to explicitly deallocate local handles. */ template class Local : public Handle { public: V8_INLINE Local(); template V8_INLINE Local(Local that) : Handle(reinterpret_cast(*that)) { /** * This check fails when trying to convert between incompatible * handles. For example, converting from a Handle to a * Handle. */ TYPE_CHECK(T, S); } template V8_INLINE static Local Cast(Local that) { #ifdef V8_ENABLE_CHECKS // If we're going to perform the type check then we have to check // that the handle isn't empty before doing the checked cast. if (that.IsEmpty()) return Local(); #endif return Local(T::Cast(*that)); } template V8_INLINE Local(Handle that) : Handle(reinterpret_cast(*that)) { TYPE_CHECK(T, S); } template V8_INLINE Local As() { return Local::Cast(*this); } /** * Create a local handle for the content of another handle. * The referee is kept alive by the local handle even when * the original handle is destroyed/disposed. */ V8_INLINE static Local New(Isolate* isolate, Handle that); template V8_INLINE static Local New(Isolate* isolate, const Persistent& that); #ifndef V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR private: #endif template V8_INLINE Local(S* that) : Handle(that) { } private: friend class Utils; template friend class Eternal; template friend class Persistent; template friend class Handle; template friend class FunctionCallbackInfo; template friend class PropertyCallbackInfo; friend class String; friend class Object; friend class Context; template friend class internal::CustomArguments; friend class HandleScope; friend class EscapableHandleScope; V8_INLINE static Local New(Isolate* isolate, T* that); }; // Eternal handles are set-once handles that live for the life of the isolate. template class Eternal { public: V8_INLINE Eternal() : index_(kInitialValue) { } template V8_INLINE Eternal(Isolate* isolate, Local handle) : index_(kInitialValue) { Set(isolate, handle); } // Can only be safely called if already set. V8_INLINE Local Get(Isolate* isolate); V8_INLINE bool IsEmpty() { return index_ == kInitialValue; } template V8_INLINE void Set(Isolate* isolate, Local handle); private: static const int kInitialValue = -1; int index_; }; template class WeakCallbackData { public: typedef void (*Callback)(const WeakCallbackData& data); V8_INLINE Isolate* GetIsolate() const { return isolate_; } V8_INLINE Local GetValue() const { return handle_; } V8_INLINE P* GetParameter() const { return parameter_; } private: friend class internal::GlobalHandles; WeakCallbackData(Isolate* isolate, Local handle, P* parameter) : isolate_(isolate), handle_(handle), parameter_(parameter) { } Isolate* isolate_; Local handle_; P* parameter_; }; // TODO(dcarney): Remove this class. template > class WeakReferenceCallbacks { public: typedef void (*Revivable)(Isolate* isolate, Persistent* object, P* parameter); }; /** * Default traits for Persistent. This class does not allow * use of the copy constructor or assignment operator. * At present kResetInDestructor is not set, but that will change in a future * version. */ template class NonCopyablePersistentTraits { public: typedef Persistent > NonCopyablePersistent; static const bool kResetInDestructor = false; template V8_INLINE static void Copy(const Persistent& source, NonCopyablePersistent* dest) { Uncompilable(); } // TODO(dcarney): come up with a good compile error here. template V8_INLINE static void Uncompilable() { TYPE_CHECK(O, Primitive); } }; /** * Helper class traits to allow copying and assignment of Persistent. * This will clone the contents of storage cell, but not any of the flags, etc. */ template struct CopyablePersistentTraits { typedef Persistent > CopyablePersistent; static const bool kResetInDestructor = true; template static V8_INLINE void Copy(const Persistent& source, CopyablePersistent* dest) { // do nothing, just allow copy } }; /** * An object reference that is independent of any handle scope. Where * a Local handle only lives as long as the HandleScope in which it was * allocated, a Persistent handle remains valid until it is explicitly * disposed. * * A persistent handle contains a reference to a storage cell within * the v8 engine which holds an object value and which is updated by * the garbage collector whenever the object is moved. A new storage * cell can be created using the constructor or Persistent::Reset and * existing handles can be disposed using Persistent::Reset. * * Copy, assignment and destructor bevavior is controlled by the traits * class M. */ template class Persistent { public: /** * A Persistent with no storage cell. */ V8_INLINE Persistent() : val_(0) { } /** * Construct a Persistent from a Handle. * When the Handle is non-empty, a new storage cell is created * pointing to the same object, and no flags are set. */ template V8_INLINE Persistent(Isolate* isolate, Handle that) : val_(New(isolate, *that)) { TYPE_CHECK(T, S); } /** * Construct a Persistent from a Persistent. * When the Persistent is non-empty, a new storage cell is created * pointing to the same object, and no flags are set. */ template V8_INLINE Persistent(Isolate* isolate, const Persistent& that) : val_(New(isolate, *that)) { TYPE_CHECK(T, S); } /** * The copy constructors and assignment operator create a Persistent * exactly as the Persistent constructor, but the Copy function from the * traits class is called, allowing the setting of flags based on the * copied Persistent. */ V8_INLINE Persistent(const Persistent& that) : val_(0) { Copy(that); } template V8_INLINE Persistent(const Persistent& that) : val_(0) { Copy(that); } V8_INLINE Persistent& operator=(const Persistent& that) { // NOLINT Copy(that); return *this; } template V8_INLINE Persistent& operator=(const Persistent& that) { // NOLINT Copy(that); return *this; } /** * The destructor will dispose the Persistent based on the * kResetInDestructor flags in the traits class. Since not calling dispose * can result in a memory leak, it is recommended to always set this flag. */ V8_INLINE ~Persistent() { if (M::kResetInDestructor) Reset(); } /** * If non-empty, destroy the underlying storage cell * IsEmpty() will return true after this call. */ V8_INLINE void Reset(); /** * If non-empty, destroy the underlying storage cell * and create a new one with the contents of other if other is non empty */ template V8_INLINE void Reset(Isolate* isolate, const Handle& other); /** * If non-empty, destroy the underlying storage cell * and create a new one with the contents of other if other is non empty */ template V8_INLINE void Reset(Isolate* isolate, const Persistent& other); V8_DEPRECATED("Use Reset instead", V8_INLINE void Dispose()) { Reset(); } V8_INLINE bool IsEmpty() const { return val_ == 0; } // TODO(dcarney): this is pretty useless, fix or remove template V8_INLINE static Persistent& Cast(Persistent& that) { // NOLINT #ifdef V8_ENABLE_CHECKS // If we're going to perform the type check then we have to check // that the handle isn't empty before doing the checked cast. if (!that.IsEmpty()) T::Cast(*that); #endif return reinterpret_cast&>(that); } // TODO(dcarney): this is pretty useless, fix or remove template V8_INLINE Persistent& As() { // NOLINT return Persistent::Cast(*this); } template V8_INLINE bool operator==(const Persistent& that) const { internal::Object** a = reinterpret_cast(**this); internal::Object** b = reinterpret_cast(*that); if (a == 0) return b == 0; if (b == 0) return false; return *a == *b; } template V8_INLINE bool operator==(const Handle& that) const { internal::Object** a = reinterpret_cast(**this); internal::Object** b = reinterpret_cast(*that); if (a == 0) return b == 0; if (b == 0) return false; return *a == *b; } template V8_INLINE bool operator!=(const Persistent& that) const { return !operator==(that); } template V8_INLINE bool operator!=(const Handle& that) const { return !operator==(that); } template V8_INLINE void SetWeak( P* parameter, typename WeakCallbackData::Callback callback); template V8_INLINE void SetWeak( P* parameter, typename WeakCallbackData::Callback callback); template V8_DEPRECATED( "Use SetWeak instead", V8_INLINE void MakeWeak( P* parameter, typename WeakReferenceCallbacks::Revivable callback)); template V8_DEPRECATED( "Use SetWeak instead", V8_INLINE void MakeWeak( P* parameter, typename WeakReferenceCallbacks::Revivable callback)); V8_INLINE void ClearWeak(); /** * Marks the reference to this object independent. Garbage collector is free * to ignore any object groups containing this object. Weak callback for an * independent handle should not assume that it will be preceded by a global * GC prologue callback or followed by a global GC epilogue callback. */ V8_INLINE void MarkIndependent(); /** * Marks the reference to this object partially dependent. Partially dependent * handles only depend on other partially dependent handles and these * dependencies are provided through object groups. It provides a way to build * smaller object groups for young objects that represent only a subset of all * external dependencies. This mark is automatically cleared after each * garbage collection. */ V8_INLINE void MarkPartiallyDependent(); V8_INLINE bool IsIndependent() const; /** Checks if the handle holds the only reference to an object. */ V8_INLINE bool IsNearDeath() const; /** Returns true if the handle's reference is weak. */ V8_INLINE bool IsWeak() const; /** * Assigns a wrapper class ID to the handle. See RetainedObjectInfo interface * description in v8-profiler.h for details. */ V8_INLINE void SetWrapperClassId(uint16_t class_id); /** * Returns the class ID previously assigned to this handle or 0 if no class ID * was previously assigned. */ V8_INLINE uint16_t WrapperClassId() const; V8_DEPRECATED("This will be removed", V8_INLINE T* ClearAndLeak()); V8_DEPRECATED("This will be removed", V8_INLINE void Clear()) { val_ = 0; } // TODO(dcarney): remove #ifndef V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR private: #endif template V8_INLINE Persistent(S* that) : val_(that) { } V8_INLINE T* operator*() const { return val_; } private: friend class Isolate; friend class Utils; template friend class Handle; template friend class Local; template friend class Persistent; template friend class ReturnValue; V8_INLINE static T* New(Isolate* isolate, T* that); template V8_INLINE void Copy(const Persistent& that); T* val_; }; /** * A stack-allocated class that governs a number of local handles. * After a handle scope has been created, all local handles will be * allocated within that handle scope until either the handle scope is * deleted or another handle scope is created. If there is already a * handle scope and a new one is created, all allocations will take * place in the new handle scope until it is deleted. After that, * new handles will again be allocated in the original handle scope. * * After the handle scope of a local handle has been deleted the * garbage collector will no longer track the object stored in the * handle and may deallocate it. The behavior of accessing a handle * for which the handle scope has been deleted is undefined. */ class V8_EXPORT HandleScope { public: HandleScope(Isolate* isolate); ~HandleScope(); template V8_DEPRECATED("Use EscapableHandleScope::Escape instead", Local Close(Handle value)); /** * Counts the number of allocated handles. */ static int NumberOfHandles(); private: /** * Creates a new handle with the given value. */ static internal::Object** CreateHandle(internal::Isolate* isolate, internal::Object* value); // Uses HeapObject to obtain the current Isolate. static internal::Object** CreateHandle(internal::HeapObject* heap_object, internal::Object* value); V8_INLINE HandleScope() {} void Initialize(Isolate* isolate); // Make it hard to create heap-allocated or illegal handle scopes by // disallowing certain operations. HandleScope(const HandleScope&); void operator=(const HandleScope&); void* operator new(size_t size); void operator delete(void*, size_t); // This Data class is accessible internally as HandleScopeData through a // typedef in the ImplementationUtilities class. class V8_EXPORT Data { public: internal::Object** next; internal::Object** limit; int level; V8_INLINE void Initialize() { next = limit = NULL; level = 0; } }; void Leave(); internal::Isolate* isolate_; internal::Object** prev_next_; internal::Object** prev_limit_; // TODO(dcarney): remove this field // Allow for the active closing of HandleScopes which allows to pass a handle // from the HandleScope being closed to the next top most HandleScope. bool is_closed_; internal::Object** RawClose(internal::Object** value); friend class ImplementationUtilities; friend class EscapableHandleScope; template friend class Handle; template friend class Local; friend class Object; friend class Context; }; /** * A HandleScope which first allocates a handle in the current scope * which will be later filled with the escape value. */ class V8_EXPORT EscapableHandleScope : public HandleScope { public: EscapableHandleScope(Isolate* isolate); V8_INLINE ~EscapableHandleScope() {} /** * Pushes the value into the previous scope and returns a handle to it. * Cannot be called twice. */ template V8_INLINE Local Escape(Local value) { internal::Object** slot = Escape(reinterpret_cast(*value)); return Local(reinterpret_cast(slot)); } private: internal::Object** Escape(internal::Object** escape_value); // Make it hard to create heap-allocated or illegal handle scopes by // disallowing certain operations. EscapableHandleScope(const EscapableHandleScope&); void operator=(const EscapableHandleScope&); void* operator new(size_t size); void operator delete(void*, size_t); internal::Object** escape_slot_; }; /** * A simple Maybe type, representing an object which may or may not have a * value. */ template struct Maybe { Maybe() : has_value(false) {} explicit Maybe(T t) : has_value(true), value(t) {} Maybe(bool has, T t) : has_value(has), value(t) {} bool has_value; T value; }; // --- Special objects --- /** * The superclass of values and API object templates. */ class V8_EXPORT Data { private: Data(); }; /** * Pre-compilation data that can be associated with a script. This * data can be calculated for a script in advance of actually * compiling it, and can be stored between compilations. When script * data is given to the compile method compilation will be faster. */ class V8_EXPORT ScriptData { // NOLINT public: virtual ~ScriptData() { } /** * Pre-compiles the specified script (context-independent). * * \param input Pointer to UTF-8 script source code. * \param length Length of UTF-8 script source code. */ static ScriptData* PreCompile(Isolate* isolate, const char* input, int length); /** * Pre-compiles the specified script (context-independent). * * NOTE: Pre-compilation using this method cannot happen on another thread * without using Lockers. * * \param source Script source code. */ static ScriptData* PreCompile(Handle source); /** * Load previous pre-compilation data. * * \param data Pointer to data returned by a call to Data() of a previous * ScriptData. Ownership is not transferred. * \param length Length of data. */ static ScriptData* New(const char* data, int length); /** * Returns the length of Data(). */ virtual int Length() = 0; /** * Returns a serialized representation of this ScriptData that can later be * passed to New(). NOTE: Serialized data is platform-dependent. */ virtual const char* Data() = 0; /** * Returns true if the source code could not be parsed. */ virtual bool HasError() = 0; }; /** * The origin, within a file, of a script. */ class ScriptOrigin { public: V8_INLINE ScriptOrigin( Handle resource_name, Handle resource_line_offset = Handle(), Handle resource_column_offset = Handle(), Handle resource_is_shared_cross_origin = Handle()) : resource_name_(resource_name), resource_line_offset_(resource_line_offset), resource_column_offset_(resource_column_offset), resource_is_shared_cross_origin_(resource_is_shared_cross_origin) { } V8_INLINE Handle ResourceName() const; V8_INLINE Handle ResourceLineOffset() const; V8_INLINE Handle ResourceColumnOffset() const; V8_INLINE Handle ResourceIsSharedCrossOrigin() const; private: Handle resource_name_; Handle resource_line_offset_; Handle resource_column_offset_; Handle resource_is_shared_cross_origin_; }; /** * A compiled JavaScript script. */ class V8_EXPORT Script { public: /** * Compiles the specified script (context-independent). * * \param source Script source code. * \param origin Script origin, owned by caller, no references are kept * when New() returns * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile() * using pre_data speeds compilation if it's done multiple times. * Owned by caller, no references are kept when New() returns. * \param script_data Arbitrary data associated with script. Using * this has same effect as calling SetData(), but allows data to be * available to compile event handlers. * \return Compiled script object (context independent; when run it * will use the currently entered context). */ static Local