Vendor raptor source files (was embedded gitlink)
Tree vendored at upstream 0019c5dd; origin + license recorded in raptor/VENDOR.txt. Windows SDL dev packages excluded via .gitignore.
This commit is contained in:
1 parent
bd3ea30d55
commit
f7c9b7a02d
809 files changed
+337824
-1
No files matched your search
@@ -0,0 +1,248 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="textscreen" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Win (32 bit) Debug">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="bin/Debug/textscreen" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
<Add directory="../../SDL2-devel-2.28.2-mingw/SDL2-2.28.2/i686-w64-mingw32/include/SDL2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-lmingw32 -lSDL2main -lSDL2" />
|
||||
<Add directory="../../SDL2-devel-2.28.2-mingw/SDL2-2.28.2/i686-w64-mingw32/lib" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Win (32 bit) Release">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="bin/Release/textscreen" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
<Add directory="../../SDL2-devel-2.28.2-mingw/SDL2-2.28.2/i686-w64-mingw32/include/SDL2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-lmingw32 -lSDL2main -lSDL2" />
|
||||
<Add directory="../../SDL2-devel-2.28.2-mingw/SDL2-2.28.2/i686-w64-mingw32/lib" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux (32 bit) Debug">
|
||||
<Option platforms="Unix;" />
|
||||
<Option output="bin/Debug/textscreen" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
<Add directory="/usr/include/SDL2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-lSDL2main -lSDL2" />
|
||||
<Add directory="/usr/lib32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux (32 bit) Release">
|
||||
<Option platforms="Unix;" />
|
||||
<Option output="bin/Release/textscreen" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
<Add directory="/usr/include/SDL2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-lSDL2main -lSDL2" />
|
||||
<Add directory="/usr/lib32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux (64 bit) Debug">
|
||||
<Option platforms="Unix;" />
|
||||
<Option output="bin/Debug/textscreen" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m64" />
|
||||
<Add option="-g" />
|
||||
<Add directory="/usr/include/SDL2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m64" />
|
||||
<Add option="-lSDL2main -lSDL2" />
|
||||
<Add directory="/usr/lib" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux (64 bit) Release">
|
||||
<Option platforms="Unix;" />
|
||||
<Option output="bin/Release/textscreen" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
<Add option="-m64" />
|
||||
<Add directory="/usr/include/SDL2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m64" />
|
||||
<Add option="-lSDL2main -lSDL2" />
|
||||
<Add directory="/usr/lib" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Win (64 bit) Debug">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="bin/Debug/textscreen" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m64" />
|
||||
<Add option="-g" />
|
||||
<Add directory="../../SDL2-devel-2.28.2-mingw/SDL2-2.28.2/x86_64-w64-mingw32/include/SDL2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m64" />
|
||||
<Add option="-lmingw32 -lSDL2main -lSDL2" />
|
||||
<Add directory="../../SDL2-devel-2.28.2-mingw/SDL2-2.28.2/x86_64-w64-mingw32/lib" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Win (64 bit) Release">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="bin/Release/textscreen" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
<Add option="-m64" />
|
||||
<Add directory="../../SDL2-devel-2.28.2-mingw/SDL2-2.28.2/x86_64-w64-mingw32/include/SDL2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m64" />
|
||||
<Add option="-lmingw32 -lSDL2main -lSDL2" />
|
||||
<Add directory="../../SDL2-devel-2.28.2-mingw/SDL2-2.28.2/x86_64-w64-mingw32/lib" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
<Add option="-m32" />
|
||||
<Add directory="../../SDL2-devel-2.0.14-mingw/SDL2-2.0.14/i686-w64-mingw32/include/SDL2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m32" />
|
||||
<Add directory="../../SDL2-devel-2.0.14-mingw/SDL2-2.0.14/i686-w64-mingw32/lib" />
|
||||
</Linker>
|
||||
<Unit filename="../include/doomkeys.h" />
|
||||
<Unit filename="../include/textscreen.h" />
|
||||
<Unit filename="../include/txt_button.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_button.h" />
|
||||
<Unit filename="../include/txt_checkbox.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_checkbox.h" />
|
||||
<Unit filename="../include/txt_conditional.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_conditional.h" />
|
||||
<Unit filename="../include/txt_desktop.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_desktop.h" />
|
||||
<Unit filename="../include/txt_dropdown.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_dropdown.h" />
|
||||
<Unit filename="../include/txt_fileselect.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_fileselect.h" />
|
||||
<Unit filename="../include/txt_gui.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_gui.h" />
|
||||
<Unit filename="../include/txt_inputbox.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_inputbox.h" />
|
||||
<Unit filename="../include/txt_io.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_io.h" />
|
||||
<Unit filename="../include/txt_label.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_label.h" />
|
||||
<Unit filename="../include/txt_main.h" />
|
||||
<Unit filename="../include/txt_radiobutton.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_radiobutton.h" />
|
||||
<Unit filename="../include/txt_scrollpane.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_scrollpane.h" />
|
||||
<Unit filename="../include/txt_sdl.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_sdl.h" />
|
||||
<Unit filename="../include/txt_separator.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_separator.h" />
|
||||
<Unit filename="../include/txt_spinctrl.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_spinctrl.h" />
|
||||
<Unit filename="../include/txt_strut.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_strut.h" />
|
||||
<Unit filename="../include/txt_table.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_table.h" />
|
||||
<Unit filename="../include/txt_utf8.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_utf8.h" />
|
||||
<Unit filename="../include/txt_widget.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_widget.h" />
|
||||
<Unit filename="../include/txt_window.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_window.h" />
|
||||
<Unit filename="../include/txt_window_action.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="../include/txt_window_action.h" />
|
||||
<Extensions />
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
||||
@@ -0,0 +1,6 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
*.a
|
||||
tags
|
||||
TAGS
|
||||
@@ -0,0 +1,32 @@
|
||||
add_library(textscreen STATIC
|
||||
textscreen.h
|
||||
txt_conditional.c txt_conditional.h
|
||||
txt_checkbox.c txt_checkbox.h
|
||||
txt_desktop.c txt_desktop.h
|
||||
txt_dropdown.c txt_dropdown.h
|
||||
txt_fileselect.c txt_fileselect.h
|
||||
txt_gui.c txt_gui.h
|
||||
txt_inputbox.c txt_inputbox.h
|
||||
txt_io.c txt_io.h
|
||||
txt_main.h
|
||||
txt_button.c txt_button.h
|
||||
txt_label.c txt_label.h
|
||||
txt_radiobutton.c txt_radiobutton.h
|
||||
txt_scrollpane.c txt_scrollpane.h
|
||||
txt_separator.c txt_separator.h
|
||||
txt_spinctrl.c txt_spinctrl.h
|
||||
txt_sdl.c txt_sdl.h
|
||||
txt_strut.c txt_strut.h
|
||||
txt_table.c txt_table.h
|
||||
txt_utf8.c txt_utf8.h
|
||||
txt_widget.c txt_widget.h
|
||||
txt_window.c txt_window.h
|
||||
txt_window_action.c txt_window_action.h)
|
||||
target_include_directories(textscreen
|
||||
INTERFACE "."
|
||||
PRIVATE "../src/")
|
||||
if(MSVC)
|
||||
target_link_libraries(textscreen SDL2::SDL2)
|
||||
else()
|
||||
target_link_libraries(textscreen m SDL2::SDL2)
|
||||
endif()
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,41 @@
|
||||
|
||||
AM_CFLAGS = -I$(top_srcdir)/src
|
||||
|
||||
CTAGS_ARGS=-I TXT_UNCAST_ARG+
|
||||
|
||||
# build this directory before the examples directory.
|
||||
|
||||
SUBDIRS = fonts . examples
|
||||
|
||||
noinst_LIBRARIES=libtextscreen.a
|
||||
|
||||
EXTRA_DIST=CMakeLists.txt Doxyfile
|
||||
|
||||
libtextscreen_a_SOURCES = \
|
||||
textscreen.h \
|
||||
txt_conditional.c txt_conditional.h \
|
||||
txt_checkbox.c txt_checkbox.h \
|
||||
txt_desktop.c txt_desktop.h \
|
||||
txt_dropdown.c txt_dropdown.h \
|
||||
txt_fileselect.c txt_fileselect.h \
|
||||
txt_gui.c txt_gui.h \
|
||||
txt_inputbox.c txt_inputbox.h \
|
||||
txt_io.c txt_io.h \
|
||||
txt_main.h \
|
||||
txt_button.c txt_button.h \
|
||||
txt_label.c txt_label.h \
|
||||
txt_radiobutton.c txt_radiobutton.h \
|
||||
txt_scrollpane.c txt_scrollpane.h \
|
||||
txt_separator.c txt_separator.h \
|
||||
txt_spinctrl.c txt_spinctrl.h \
|
||||
txt_sdl.c txt_sdl.h \
|
||||
txt_strut.c txt_strut.h \
|
||||
txt_table.c txt_table.h \
|
||||
txt_utf8.c txt_utf8.h \
|
||||
txt_widget.c txt_widget.h \
|
||||
txt_window.c txt_window.h \
|
||||
txt_window_action.c txt_window_action.h
|
||||
|
||||
doc:
|
||||
doxygen
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Key definitions
|
||||
//
|
||||
|
||||
#ifndef __DOOMKEYS__
|
||||
#define __DOOMKEYS__
|
||||
|
||||
//
|
||||
// DOOM keyboard definition.
|
||||
// This is the stuff configured by Setup.Exe.
|
||||
// Most key data are simple ascii (uppercased).
|
||||
//
|
||||
#define KEY_RIGHTARROW 0xae
|
||||
#define KEY_LEFTARROW 0xac
|
||||
#define KEY_UPARROW 0xad
|
||||
#define KEY_DOWNARROW 0xaf
|
||||
#define KEY_ESCAPE 27
|
||||
#define KEY_ENTER 13
|
||||
#define KEY_TAB 9
|
||||
#define KEY_F1 (0x80+0x3b)
|
||||
#define KEY_F2 (0x80+0x3c)
|
||||
#define KEY_F3 (0x80+0x3d)
|
||||
#define KEY_F4 (0x80+0x3e)
|
||||
#define KEY_F5 (0x80+0x3f)
|
||||
#define KEY_F6 (0x80+0x40)
|
||||
#define KEY_F7 (0x80+0x41)
|
||||
#define KEY_F8 (0x80+0x42)
|
||||
#define KEY_F9 (0x80+0x43)
|
||||
#define KEY_F10 (0x80+0x44)
|
||||
#define KEY_F11 (0x80+0x57)
|
||||
#define KEY_F12 (0x80+0x58)
|
||||
|
||||
#define KEY_BACKSPACE 0x7f
|
||||
#define KEY_PAUSE 0xff
|
||||
|
||||
#define KEY_EQUALS 0x3d
|
||||
#define KEY_MINUS 0x2d
|
||||
|
||||
#define KEY_RSHIFT (0x80+0x36)
|
||||
#define KEY_RCTRL (0x80+0x1d)
|
||||
#define KEY_RALT (0x80+0x38)
|
||||
|
||||
#define KEY_LALT KEY_RALT
|
||||
|
||||
// new keys:
|
||||
|
||||
#define KEY_CAPSLOCK (0x80+0x3a)
|
||||
#define KEY_NUMLOCK (0x80+0x45)
|
||||
#define KEY_SCRLCK (0x80+0x46)
|
||||
#define KEY_PRTSCR (0x80+0x59)
|
||||
|
||||
#define KEY_HOME (0x80+0x47)
|
||||
#define KEY_END (0x80+0x4f)
|
||||
#define KEY_PGUP (0x80+0x49)
|
||||
#define KEY_PGDN (0x80+0x51)
|
||||
#define KEY_INS (0x80+0x52)
|
||||
#define KEY_DEL (0x80+0x53)
|
||||
|
||||
#define KEYP_0 KEY_INS
|
||||
#define KEYP_1 KEY_END
|
||||
#define KEYP_2 KEY_DOWNARROW
|
||||
#define KEYP_3 KEY_PGDN
|
||||
#define KEYP_4 KEY_LEFTARROW
|
||||
#define KEYP_5 (0x80+0x4c)
|
||||
#define KEYP_6 KEY_RIGHTARROW
|
||||
#define KEYP_7 KEY_HOME
|
||||
#define KEYP_8 KEY_UPARROW
|
||||
#define KEYP_9 KEY_PGUP
|
||||
|
||||
#define KEYP_DIVIDE '/'
|
||||
#define KEYP_PLUS '+'
|
||||
#define KEYP_MINUS '-'
|
||||
#define KEYP_MULTIPLY '*'
|
||||
#define KEYP_PERIOD 0
|
||||
#define KEYP_EQUALS KEY_EQUALS
|
||||
#define KEYP_ENTER KEY_ENTER
|
||||
|
||||
#define SCANCODE_TO_KEYS_ARRAY { \
|
||||
0, 0, 0, 0, 'a', /* 0-9 */ \
|
||||
'b', 'c', 'd', 'e', 'f', \
|
||||
'g', 'h', 'i', 'j', 'k', /* 10-19 */ \
|
||||
'l', 'm', 'n', 'o', 'p', \
|
||||
'q', 'r', 's', 't', 'u', /* 20-29 */ \
|
||||
'v', 'w', 'x', 'y', 'z', \
|
||||
'1', '2', '3', '4', '5', /* 30-39 */ \
|
||||
'6', '7', '8', '9', '0', \
|
||||
KEY_ENTER, KEY_ESCAPE, KEY_BACKSPACE, KEY_TAB, ' ', /* 40-49 */ \
|
||||
KEY_MINUS, KEY_EQUALS, '[', ']', '\\', \
|
||||
0, ';', '\'', '`', ',', /* 50-59 */ \
|
||||
'.', '/', KEY_CAPSLOCK, KEY_F1, KEY_F2, \
|
||||
KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* 60-69 */ \
|
||||
KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, \
|
||||
KEY_PRTSCR, KEY_SCRLCK, KEY_PAUSE, KEY_INS, KEY_HOME, /* 70-79 */ \
|
||||
KEY_PGUP, KEY_DEL, KEY_END, KEY_PGDN, KEY_RIGHTARROW, \
|
||||
KEY_LEFTARROW, KEY_DOWNARROW, KEY_UPARROW, /* 80-89 */ \
|
||||
KEY_NUMLOCK, KEYP_DIVIDE, \
|
||||
KEYP_MULTIPLY, KEYP_MINUS, KEYP_PLUS, KEYP_ENTER, KEYP_1, \
|
||||
KEYP_2, KEYP_3, KEYP_4, KEYP_5, KEYP_6, /* 90-99 */ \
|
||||
KEYP_7, KEYP_8, KEYP_9, KEYP_0, KEYP_PERIOD, \
|
||||
0, 0, 0, KEYP_EQUALS, /* 100-103 */ \
|
||||
}
|
||||
|
||||
// Default names for keys, to use in English or as fallback.
|
||||
#define KEY_NAMES_ARRAY { \
|
||||
{ KEY_BACKSPACE, "BACKSP" }, { KEY_TAB, "TAB" }, \
|
||||
{ KEY_INS, "INS" }, { KEY_DEL, "DEL" }, \
|
||||
{ KEY_PGUP, "PGUP" }, { KEY_PGDN, "PGDN" }, \
|
||||
{ KEY_ENTER, "ENTER" }, { KEY_ESCAPE, "ESC" }, \
|
||||
{ KEY_F1, "F1" }, { KEY_F2, "F2" }, \
|
||||
{ KEY_F3, "F3" }, { KEY_F4, "F4" }, \
|
||||
{ KEY_F5, "F5" }, { KEY_F6, "F6" }, \
|
||||
{ KEY_F7, "F7" }, { KEY_F8, "F8" }, \
|
||||
{ KEY_F9, "F9" }, { KEY_F10, "F10" }, \
|
||||
{ KEY_F11, "F11" }, { KEY_F12, "F12" }, \
|
||||
{ KEY_HOME, "HOME" }, { KEY_END, "END" }, \
|
||||
{ KEY_MINUS, "-" }, { KEY_EQUALS, "=" }, \
|
||||
{ KEY_NUMLOCK, "NUMLCK" }, { KEY_SCRLCK, "SCRLCK" }, \
|
||||
{ KEY_PAUSE, "PAUSE" }, { KEY_PRTSCR, "PRTSC" }, \
|
||||
{ KEY_UPARROW, "UP" }, { KEY_DOWNARROW, "DOWN" }, \
|
||||
{ KEY_LEFTARROW, "LEFT" }, { KEY_RIGHTARROW, "RIGHT" }, \
|
||||
{ KEY_RALT, "ALT" }, { KEY_LALT, "ALT" }, \
|
||||
{ KEY_RSHIFT, "SHIFT" }, { KEY_CAPSLOCK, "CAPS" }, \
|
||||
{ KEY_RCTRL, "CTRL" }, { KEYP_5, "NUM5" }, \
|
||||
{ ' ', "SPACE" }, \
|
||||
{ 'a', "A" }, { 'b', "B" }, { 'c', "C" }, { 'd', "D" }, \
|
||||
{ 'e', "E" }, { 'f', "F" }, { 'g', "G" }, { 'h', "H" }, \
|
||||
{ 'i', "I" }, { 'j', "J" }, { 'k', "K" }, { 'l', "L" }, \
|
||||
{ 'm', "M" }, { 'n', "N" }, { 'o', "O" }, { 'p', "P" }, \
|
||||
{ 'q', "Q" }, { 'r', "R" }, { 's', "S" }, { 't', "T" }, \
|
||||
{ 'u', "U" }, { 'v', "V" }, { 'w', "W" }, { 'x', "X" }, \
|
||||
{ 'y', "Y" }, { 'z', "Z" }, { '0', "0" }, { '1', "1" }, \
|
||||
{ '2', "2" }, { '3', "3" }, { '4', "4" }, { '5', "5" }, \
|
||||
{ '6', "6" }, { '7', "7" }, { '8', "8" }, { '9', "9" }, \
|
||||
{ '[', "[" }, { ']', "]" }, { ';', ";" }, { '`', "`" }, \
|
||||
{ ',', "," }, { '.', "." }, { '/', "/" }, { '\\', "\\" }, \
|
||||
{ '\'', "\'" }, \
|
||||
}
|
||||
|
||||
#endif // __DOOMKEYS__
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
.deps
|
||||
guitest
|
||||
calculator
|
||||
*.exe
|
||||
tags
|
||||
TAGS
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/textscreen
|
||||
|
||||
noinst_PROGRAMS=guitest calculator
|
||||
|
||||
guitest_LDADD = ../libtextscreen.a @LDFLAGS@ @SDL_LIBS@
|
||||
guitest_SOURCES = guitest.c
|
||||
|
||||
calculator_LDADD = ../libtextscreen.a @LDFLAGS@ @SDL_LIBS@
|
||||
calculator_SOURCES = calculator.c
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Example program: desktop calculator
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "textscreen.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OP_NONE,
|
||||
OP_PLUS,
|
||||
OP_MINUS,
|
||||
OP_MULT,
|
||||
OP_DIV,
|
||||
} operator_t;
|
||||
|
||||
int starting_input = 0;
|
||||
int input_value = 0;
|
||||
txt_label_t *input_box;
|
||||
int first_operand;
|
||||
operator_t operator = OP_NONE;
|
||||
|
||||
void UpdateInputBox(void)
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
TXT_snprintf(buf, sizeof(buf), " %i", input_value);
|
||||
TXT_SetLabel(input_box, buf);
|
||||
}
|
||||
|
||||
void InsertNumber(TXT_UNCAST_ARG(button), TXT_UNCAST_ARG(value))
|
||||
{
|
||||
TXT_CAST_ARG(int, value);
|
||||
|
||||
if (starting_input)
|
||||
{
|
||||
input_value = 0;
|
||||
starting_input = 0;
|
||||
}
|
||||
|
||||
input_value *= 10;
|
||||
input_value += *value;
|
||||
UpdateInputBox();
|
||||
}
|
||||
|
||||
void AddNumberButton(txt_table_t *table, int value)
|
||||
{
|
||||
char buf[10];
|
||||
int *val_copy;
|
||||
|
||||
val_copy = malloc(sizeof(int));
|
||||
*val_copy = value;
|
||||
|
||||
TXT_snprintf(buf, sizeof(buf), " %i ", value);
|
||||
|
||||
TXT_AddWidget(table, TXT_NewButton2(buf, InsertNumber, val_copy));
|
||||
}
|
||||
|
||||
void Operator(TXT_UNCAST_ARG(button), TXT_UNCAST_ARG(op))
|
||||
{
|
||||
TXT_CAST_ARG(operator_t, op);
|
||||
|
||||
first_operand = input_value;
|
||||
operator = *op;
|
||||
starting_input = 1;
|
||||
}
|
||||
|
||||
void AddOperatorButton(txt_table_t *table, const char *label, operator_t op)
|
||||
{
|
||||
char buf[10];
|
||||
operator_t *op_copy;
|
||||
|
||||
op_copy = malloc(sizeof(operator_t));
|
||||
*op_copy = op;
|
||||
|
||||
TXT_snprintf(buf, sizeof(buf), " %s ", label);
|
||||
|
||||
TXT_AddWidget(table, TXT_NewButton2(buf, Operator, op_copy));
|
||||
}
|
||||
|
||||
void Calculate(TXT_UNCAST_ARG(button), void *unused)
|
||||
{
|
||||
switch (operator)
|
||||
{
|
||||
case OP_PLUS:
|
||||
input_value = first_operand + input_value;
|
||||
break;
|
||||
case OP_MINUS:
|
||||
input_value = first_operand - input_value;
|
||||
break;
|
||||
case OP_MULT:
|
||||
input_value = first_operand * input_value;
|
||||
break;
|
||||
case OP_DIV:
|
||||
input_value = first_operand / input_value;
|
||||
break;
|
||||
case OP_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateInputBox();
|
||||
|
||||
operator = OP_NONE;
|
||||
starting_input = 1;
|
||||
}
|
||||
|
||||
void BuildGUI()
|
||||
{
|
||||
txt_window_t *window;
|
||||
txt_table_t *table;
|
||||
|
||||
window = TXT_NewWindow("Calculator");
|
||||
|
||||
input_box = TXT_NewLabel("asdf");
|
||||
TXT_SetBGColor(input_box, TXT_COLOR_BLACK);
|
||||
TXT_AddWidget(window, input_box);
|
||||
TXT_AddWidget(window, TXT_NewSeparator(NULL));
|
||||
TXT_AddWidget(window, TXT_NewStrut(0, 1));
|
||||
|
||||
table = TXT_NewTable(4);
|
||||
TXT_AddWidget(window, table);
|
||||
TXT_SetWidgetAlign(table, TXT_HORIZ_CENTER);
|
||||
|
||||
AddNumberButton(table, 7);
|
||||
AddNumberButton(table, 8);
|
||||
AddNumberButton(table, 9);
|
||||
AddOperatorButton(table, "*", OP_MULT);
|
||||
AddNumberButton(table, 4);
|
||||
AddNumberButton(table, 5);
|
||||
AddNumberButton(table, 6);
|
||||
AddOperatorButton(table, "-", OP_MINUS);
|
||||
AddNumberButton(table, 1);
|
||||
AddNumberButton(table, 2);
|
||||
AddNumberButton(table, 3);
|
||||
AddOperatorButton(table, "+", OP_PLUS);
|
||||
AddNumberButton(table, 0);
|
||||
TXT_AddWidget(table, NULL);
|
||||
|
||||
TXT_AddWidget(table, TXT_NewButton2(" = ", Calculate, NULL));
|
||||
AddOperatorButton(table, "/", OP_DIV);
|
||||
|
||||
TXT_AddWidget(window, TXT_NewStrut(0, 1));
|
||||
UpdateInputBox();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (!TXT_Init())
|
||||
{
|
||||
fprintf(stderr, "Failed to initialise GUI\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
TXT_SetDesktopTitle("Calculator demo");
|
||||
|
||||
BuildGUI();
|
||||
|
||||
TXT_GUIMainLoop();
|
||||
|
||||
TXT_Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Example program: GUI test program
|
||||
//
|
||||
// Demonstrates all the main textscreen widgets in use and shows how
|
||||
// a simple textscreen program can be written.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "textscreen.h"
|
||||
|
||||
enum
|
||||
{
|
||||
RADIO_VALUE_BADGER,
|
||||
RADIO_VALUE_MUSHROOM,
|
||||
RADIO_VALUE_SNAKE,
|
||||
};
|
||||
|
||||
// also put some crazy extensions to test the escape function. a"b"c"""dd
|
||||
const char *extensions[] = { "wad", "lmp", "txt", "a\"b\"c\"\"\"dd", "",
|
||||
"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"", NULL };
|
||||
const char *radio_values[] = { "Badger", "Mushroom", "Snake" };
|
||||
char *textbox_value = NULL;
|
||||
int numbox_value = 0;
|
||||
int radiobutton_value;
|
||||
char *file_path = NULL;
|
||||
char *dir_path = NULL;
|
||||
txt_label_t *value_label;
|
||||
txt_window_t *firstwin;
|
||||
int cheesy;
|
||||
|
||||
void ClosePwnBox(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(window))
|
||||
{
|
||||
TXT_CAST_ARG(txt_window_t, window);
|
||||
|
||||
TXT_CloseWindow(window);
|
||||
}
|
||||
|
||||
void PwnBox(TXT_UNCAST_ARG(widget), void *user_data)
|
||||
{
|
||||
txt_window_t *window;
|
||||
txt_window_action_t *close_button;
|
||||
|
||||
window = TXT_NewWindow("Pwned!");
|
||||
TXT_AddWidget(window, TXT_NewLabel(" BOOM! HEADSHOT! "));
|
||||
|
||||
close_button = TXT_NewWindowAction(KEY_ENTER, "Close");
|
||||
TXT_SignalConnect(close_button, "pressed", ClosePwnBox, window);
|
||||
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL);
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, close_button);
|
||||
}
|
||||
|
||||
void UpdateLabel(TXT_UNCAST_ARG(widget), void *user_data)
|
||||
{
|
||||
char buf[40];
|
||||
|
||||
TXT_StringCopy(buf, " Current value: ", sizeof(buf));
|
||||
if (cheesy)
|
||||
{
|
||||
TXT_StringConcat(buf, "Cheesy ", sizeof(buf));
|
||||
}
|
||||
TXT_StringConcat(buf, radio_values[radiobutton_value], sizeof(buf));
|
||||
TXT_StringConcat(buf, "\n", sizeof(buf));
|
||||
|
||||
TXT_SetLabel(value_label, buf);
|
||||
}
|
||||
|
||||
void CloseWindow(TXT_UNCAST_ARG(button), void *user_data)
|
||||
{
|
||||
TXT_CloseWindow(firstwin);
|
||||
}
|
||||
|
||||
void UnicodeWindow(TXT_UNCAST_ARG(widget), void *user_data)
|
||||
{
|
||||
static const char *strings[] = {
|
||||
"lunedì", "martedì", "mercoledì", "giovedì",
|
||||
"venerdì", "sabato", "domenica",
|
||||
};
|
||||
static int var1, var2;
|
||||
txt_window_t *window;
|
||||
|
||||
window = TXT_NewWindow("Questo è in Italiano");
|
||||
|
||||
TXT_AddWidgets(window,
|
||||
TXT_NewButton("Questo è un tasto"),
|
||||
TXT_NewCheckBox("Questo è un checkbox", &var1),
|
||||
TXT_NewDropdownList(&var2, strings, 7),
|
||||
TXT_NewSeparator("Questo è un separatore"),
|
||||
TXT_NewLabel("Leggi questo, è pieno di\n"
|
||||
"informazioni interessanti"),
|
||||
TXT_NewRadioButton("Ma questo non è un radio??",
|
||||
&var1, 0),
|
||||
NULL);
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_RIGHT,
|
||||
TXT_NewWindowAction(KEY_ENTER, "Nullità"));
|
||||
|
||||
}
|
||||
|
||||
void SetupWindow(void)
|
||||
{
|
||||
txt_window_t *window;
|
||||
txt_table_t *table;
|
||||
txt_table_t *rightpane;
|
||||
txt_checkbox_t *cheesy_checkbox;
|
||||
txt_window_action_t *pwn;
|
||||
txt_label_t *toplabel;
|
||||
char buf[100];
|
||||
int i;
|
||||
|
||||
window = TXT_NewWindow("Window test");
|
||||
|
||||
TXT_SetWindowHelpURL(window, "https://www.youtube.com/watch?v=dQw4w9WgXcQ");
|
||||
|
||||
TXT_AddWidget(window, TXT_NewSeparator("Main section"));
|
||||
table = TXT_NewTable(3);
|
||||
|
||||
toplabel = TXT_NewLabel("This is a multiline label.\n"
|
||||
"A single label object contains \n"
|
||||
"all three of these lines.");
|
||||
TXT_AddWidget(window, toplabel);
|
||||
TXT_SetWidgetAlign(toplabel, TXT_HORIZ_CENTER);
|
||||
|
||||
//TXT_AddWidget(window, TXT_NewScrollPane(15, 4, table));
|
||||
TXT_AddWidget(window, table);
|
||||
|
||||
for (i=0; i<3; ++i)
|
||||
{
|
||||
TXT_snprintf(buf, sizeof(buf), "Option %i in a table:", i + 1);
|
||||
TXT_AddWidget(table, TXT_NewLabel(buf));
|
||||
TXT_snprintf(buf, sizeof(buf), " Button %i-1 ", i + 1);
|
||||
TXT_AddWidget(table, TXT_NewButton(buf));
|
||||
TXT_snprintf(buf, sizeof(buf), " Button %i-2 ", i + 1);
|
||||
TXT_AddWidget(table, TXT_NewButton(buf));
|
||||
}
|
||||
|
||||
TXT_AddWidgets(table,
|
||||
TXT_NewLabel("Still the same table, but:\n"
|
||||
"This label magically overflows\n"
|
||||
"across multiple cells! Cool, huh? "),
|
||||
TXT_TABLE_OVERFLOW_RIGHT,
|
||||
TXT_NewButton("Do nothing"),
|
||||
TXT_TABLE_OVERFLOW_DOWN,
|
||||
TXT_TABLE_OVERFLOW_DOWN,
|
||||
TXT_NewButton2("Qualcosa?", UnicodeWindow, NULL),
|
||||
NULL);
|
||||
|
||||
TXT_AddWidget(window, TXT_NewStrut(0, 1));
|
||||
value_label = TXT_NewLabel("");
|
||||
TXT_AddWidget(window, value_label);
|
||||
|
||||
table = TXT_NewTable(2);
|
||||
TXT_AddWidget(window, table);
|
||||
TXT_SetWidgetAlign(table, TXT_HORIZ_CENTER);
|
||||
|
||||
cheesy_checkbox = TXT_NewCheckBox("Cheesy", &cheesy);
|
||||
TXT_AddWidget(table, cheesy_checkbox);
|
||||
TXT_SignalConnect(cheesy_checkbox, "changed", UpdateLabel, NULL);
|
||||
|
||||
rightpane = TXT_NewTable(1);
|
||||
TXT_AddWidget(table, rightpane);
|
||||
|
||||
for (i=0; i<3; ++i)
|
||||
{
|
||||
txt_radiobutton_t *rbut;
|
||||
|
||||
rbut = TXT_NewRadioButton(radio_values[i], &radiobutton_value, i);
|
||||
TXT_AddWidget(rightpane, rbut);
|
||||
TXT_SignalConnect(rbut, "selected", UpdateLabel, NULL);
|
||||
}
|
||||
|
||||
UpdateLabel(NULL, NULL);
|
||||
|
||||
TXT_AddWidget(window, TXT_NewButton2("Close Window", CloseWindow, NULL));
|
||||
|
||||
pwn = TXT_NewWindowAction(KEY_F1, "PWN!");
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_CENTER, pwn);
|
||||
TXT_SignalConnect(pwn, "pressed", PwnBox, NULL);
|
||||
|
||||
firstwin = window;
|
||||
}
|
||||
|
||||
void Window2(void)
|
||||
{
|
||||
txt_window_t *window;
|
||||
txt_table_t *table;
|
||||
txt_table_t *unselectable_table;
|
||||
txt_scrollpane_t *scrollpane;
|
||||
|
||||
window = TXT_NewWindow("Another test");
|
||||
TXT_SetWindowPosition(window,
|
||||
TXT_HORIZ_RIGHT,
|
||||
TXT_VERT_TOP,
|
||||
TXT_SCREEN_W - 1, 1);
|
||||
|
||||
TXT_AddWidgets(window,
|
||||
TXT_NewScrollPane(40, 1,
|
||||
TXT_NewLabel("* Unselectable scroll pane *")),
|
||||
unselectable_table = TXT_NewTable(1),
|
||||
NULL);
|
||||
|
||||
TXT_AddWidget(unselectable_table, TXT_NewLabel("* Unselectable table *"));
|
||||
TXT_AddWidget(unselectable_table, TXT_NewLabel(
|
||||
"This is a UTF-8 string:\n"
|
||||
"\xc3\x80 bient\xc3\xb4t na\xc3\xaet "
|
||||
"\xc3\xa9v\xc3\xaaque \xc3\xa0 l'\xc5\x93uvre p\xc3\xa8re."));
|
||||
|
||||
TXT_AddWidget(window, TXT_NewSeparator("Input boxes"));
|
||||
table = TXT_NewTable(2);
|
||||
TXT_AddWidget(window, table);
|
||||
TXT_AddWidgets(table,
|
||||
TXT_NewLabel("String: "),
|
||||
TXT_NewInputBox(&textbox_value, 20),
|
||||
TXT_NewLabel("Int: "),
|
||||
TXT_NewIntInputBox(&numbox_value, 10),
|
||||
TXT_NewLabel("Spin control:"),
|
||||
TXT_NewSpinControl(&numbox_value, 0, 15),
|
||||
TXT_NewLabel("File:"),
|
||||
TXT_NewFileSelector(&file_path, 28, "Select file:",
|
||||
extensions),
|
||||
TXT_NewLabel("Directory:"),
|
||||
TXT_NewFileSelector(&dir_path, 28, "Select directory:",
|
||||
TXT_DIRECTORY),
|
||||
NULL);
|
||||
|
||||
TXT_AddWidget(window, TXT_NewSeparator("Scroll pane test"));
|
||||
scrollpane = TXT_NewScrollPane(40, 5, TXT_NewLabel(
|
||||
"This is a scrollable pane. The contents\n"
|
||||
"of this box are larger than the box\n"
|
||||
"itself, but it can be scrolled around\n"
|
||||
"to explore the full contents.\n"
|
||||
"\n"
|
||||
"Scrollable panes can be scrolled both\n"
|
||||
"vertically and horizontally. They\n"
|
||||
"can contain any widget. The scroll bars\n"
|
||||
"appear automatically as needed.\n"
|
||||
"\n"
|
||||
"This is a very long line of text that forces a horizontal scrollbar"
|
||||
));
|
||||
TXT_AddWidget(window, scrollpane);
|
||||
}
|
||||
|
||||
void ScrollingMenu(void)
|
||||
{
|
||||
txt_window_t *window;
|
||||
txt_button_t *button;
|
||||
txt_table_t *table;
|
||||
|
||||
window = TXT_NewWindow("Scrollable menu");
|
||||
|
||||
table = TXT_NewTable(1);
|
||||
|
||||
TXT_AddWidgets(table,
|
||||
TXT_NewButton("Configure display"),
|
||||
TXT_NewButton("Configure joystick"),
|
||||
TXT_NewButton("Configure keyboard"),
|
||||
TXT_NewButton("Configure mouse"),
|
||||
TXT_NewButton("Configure sound"),
|
||||
TXT_NewStrut(0, 1),
|
||||
button = TXT_NewButton("Save Parameters and launch DOOM"),
|
||||
TXT_NewStrut(0, 1),
|
||||
TXT_NewButton("Start a network game"),
|
||||
TXT_NewButton("Join a network game"),
|
||||
TXT_NewButton("Multiplayer configuration"),
|
||||
NULL);
|
||||
|
||||
TXT_SignalConnect(button, "pressed", PwnBox, NULL);
|
||||
|
||||
TXT_AddWidget(window, TXT_NewScrollPane(0, 6, table));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (!TXT_Init())
|
||||
{
|
||||
fprintf(stderr, "Failed to initialise GUI\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
TXT_SetDesktopTitle("Not Chocolate Doom Setup");
|
||||
|
||||
ScrollingMenu();
|
||||
Window2();
|
||||
SetupWindow();
|
||||
|
||||
TXT_GUIMainLoop();
|
||||
|
||||
TXT_Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
FONT_HDRS = small.h normal.h large.h codepage.h
|
||||
EXTRA_DIST = small.png normal.png large.png convert-font $(FONT_HDRS)
|
||||
|
||||
noinst_DATA = $(FONT_HDRS)
|
||||
|
||||
if HAVE_FONTS
|
||||
|
||||
small.h: small.png convert-font
|
||||
$(srcdir)/convert-font small small.png small.h
|
||||
|
||||
normal.h: normal.png convert-font
|
||||
$(srcdir)/convert-font normal normal.png normal.h
|
||||
|
||||
large.h: large.png convert-font
|
||||
$(srcdir)/convert-font large large.png large.h
|
||||
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
This directory contains the fonts used by libtextscreen:
|
||||
|
||||
* normal.png is the standard DOS font, from the DOSbox project.
|
||||
Copyright (C) 2002-2004 The DOSBox Team
|
||||
|
||||
* small.png contains a miniature, half-size font for low-resolution
|
||||
displays. This is based on the Atari-Small font by Tom Fine. The
|
||||
original font was standard ASCII only; this has been extended to the
|
||||
full Extended ASCII range with scaled-down versions of the full-size
|
||||
DOS font. Original copyright notice:
|
||||
|
||||
Copyright (c) 1999, Thomas A. Fine
|
||||
|
||||
License to copy, modify, and distribute for both commercial and
|
||||
non-commercial use is herby granted, provided this notice
|
||||
is preserved.
|
||||
|
||||
Email to my last name at head.cfa.harvard.edu
|
||||
http://hea-www.harvard.edu/~fine/
|
||||
|
||||
* large.png is a scaled-up version of normal.png with extra detail
|
||||
added; this is for use on modern high-resolution ("retina") displays.
|
||||
|
||||
All modifications and enhancements to the above fonts are:
|
||||
|
||||
Copyright (C) 2005-2016 Simon Howard
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright(C) 2017 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
// This file contains a #define macro mapping from the characters
|
||||
// in the CP437 code page to the equivalent Unicode characters. It
|
||||
// therefore defines which Unicode characters can be represented on
|
||||
// a text screen using such a code page.
|
||||
//
|
||||
// If you're changing the textscreen font to show a different code
|
||||
// page, you should update the mapping in this file to match. The
|
||||
// Wikipedia pages for DOS code pages are a good place to look for
|
||||
// this information.
|
||||
|
||||
#define CODE_PAGE_TO_UNICODE { \
|
||||
\
|
||||
/* CP437 control codes: */ \
|
||||
\
|
||||
0x0000, 0x263a, 0x263b, 0x2665, /* 00 - 0f */ \
|
||||
0x2666, 0x2663, 0x2660, 0x2022, \
|
||||
0x25d8, 0x25cb, 0x25d9, 0x2642, \
|
||||
0x2640, 0x266a, 0x266b, 0x263c, \
|
||||
\
|
||||
0x25ba, 0x25c4, 0x2195, 0x203c, /* 10 - 1f */ \
|
||||
0x00b6, 0x00a7, 0x25ac, 0x21a8, \
|
||||
0x2191, 0x2193, 0x2192, 0x2190, \
|
||||
0x221f, 0x2194, 0x25b2, 0x25bc, \
|
||||
\
|
||||
/* Standard ASCII range: */ \
|
||||
\
|
||||
0x0020, 0x0021, 0x0022, 0x0023, /* 20 - 2f */ \
|
||||
0x0024, 0x0025, 0x0026, 0x0027, \
|
||||
0x0028, 0x0029, 0x002a, 0x002b, \
|
||||
0x002c, 0x002d, 0x002e, 0x002f, \
|
||||
\
|
||||
0x0030, 0x0031, 0x0032, 0x0033, /* 30 - 3f */ \
|
||||
0x0034, 0x0035, 0x0036, 0x0037, \
|
||||
0x0038, 0x0039, 0x003a, 0x003b, \
|
||||
0x003c, 0x003d, 0x003e, 0x003f, \
|
||||
\
|
||||
0x0040, 0x0041, 0x0042, 0x0043, /* 40 - 4f */ \
|
||||
0x0044, 0x0045, 0x0046, 0x0047, \
|
||||
0x0048, 0x0049, 0x004a, 0x004b, \
|
||||
0x004c, 0x004d, 0x004e, 0x004f, \
|
||||
\
|
||||
0x0050, 0x0051, 0x0052, 0x0053, /* 50 - 5f */ \
|
||||
0x0054, 0x0055, 0x0056, 0x0057, \
|
||||
0x0058, 0x0059, 0x005a, 0x005b, \
|
||||
0x005c, 0x005d, 0x005e, 0x005f, \
|
||||
\
|
||||
0x0060, 0x0061, 0x0062, 0x0063, /* 60 - 6f */ \
|
||||
0x0064, 0x0065, 0x0066, 0x0067, \
|
||||
0x0068, 0x0069, 0x006a, 0x006b, \
|
||||
0x006c, 0x006d, 0x006e, 0x006f, \
|
||||
\
|
||||
0x0070, 0x0071, 0x0072, 0x0073, /* 70 - 7f */ \
|
||||
0x0074, 0x0075, 0x0076, 0x0077, \
|
||||
0x0078, 0x0079, 0x007a, 0x007b, \
|
||||
0x007c, 0x007d, 0x007e, 0x2302, \
|
||||
\
|
||||
/* CP437 Extended ASCII range: */ \
|
||||
\
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, /* 80-8f */ \
|
||||
0x00e4, 0x00e0, 0x00e5, 0x00e7, \
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, \
|
||||
0x00ee, 0x00ec, 0x00c4, 0x00c5, \
|
||||
\
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, /* 90-9f */ \
|
||||
0x00f6, 0x00f2, 0x00fb, 0x00f9, \
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, \
|
||||
0x00a3, 0x00a5, 0x20a7, 0x0192, \
|
||||
\
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, /* a0-af */ \
|
||||
0x00f1, 0x00d1, 0x00aa, 0x00ba, \
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, \
|
||||
0x00bc, 0x00a1, 0x00ab, 0x00bb, \
|
||||
\
|
||||
0x2591, 0x2592, 0x2593, 0x2502, /* b0-bf */ \
|
||||
0x2524, 0x2561, 0x2562, 0x2556, \
|
||||
0x2555, 0x2563, 0x2551, 0x2557, \
|
||||
0x255d, 0x255c, 0x255b, 0x2510, \
|
||||
\
|
||||
0x2514, 0x2534, 0x252c, 0x251c, /* c0-cf */ \
|
||||
0x2500, 0x253c, 0x255e, 0x255f, \
|
||||
0x255a, 0x2554, 0x2569, 0x2566, \
|
||||
0x2560, 0x2550, 0x256c, 0x2567, \
|
||||
\
|
||||
0x2568, 0x2564, 0x2565, 0x2559, /* d0-df */ \
|
||||
0x2558, 0x2552, 0x2553, 0x256b, \
|
||||
0x256a, 0x2518, 0x250c, 0x2588, \
|
||||
0x2584, 0x258c, 0x2590, 0x2580, \
|
||||
\
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, /* e0-ef */ \
|
||||
0x03a3, 0x03c3, 0x00b5, 0x03c4, \
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, \
|
||||
0x221e, 0x03c6, 0x03b5, 0x2229, \
|
||||
\
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, /* f0-ff */ \
|
||||
0x2320, 0x2321, 0x00f7, 0x2248, \
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, \
|
||||
0x207f, 0x00b2, 0x25a0, 0x00a0, \
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright(C) 2016 Simon Howard
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
#
|
||||
# Converts images into libtextscreen fonts.
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
GRID_COLUMNS = 16
|
||||
GRID_ROWS = 16
|
||||
|
||||
try:
|
||||
import Image
|
||||
except ImportError:
|
||||
try:
|
||||
from PIL import Image
|
||||
except ImportError:
|
||||
print("WARNING: Could not update %s. "
|
||||
"Please install the Python Imaging library or Pillow."
|
||||
% sys.argv[3])
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def generate_font_data(filename):
|
||||
"""Read font data from the given file.
|
||||
|
||||
Args:
|
||||
filename: Image file to read.
|
||||
Returns:
|
||||
Tuple containing:
|
||||
(width, height) dimensions of each font character.
|
||||
Array of byte data for font.
|
||||
"""
|
||||
im = Image.open(filename)
|
||||
width, height = im.size
|
||||
assert (width % GRID_COLUMNS) == 0
|
||||
assert (height % GRID_ROWS) == 0
|
||||
|
||||
char_w, char_h = width // GRID_COLUMNS, height // GRID_ROWS
|
||||
font_data_len = (width * height) // 8
|
||||
font_data = [0] * font_data_len
|
||||
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
px = im.getpixel((x, y))
|
||||
if px > (127, 127, 127):
|
||||
char_x, char_y = x // char_w, y // char_h
|
||||
x1, y1 = x % char_w, y % char_h
|
||||
bit_index = (
|
||||
(char_y * GRID_COLUMNS + char_x) * (char_w * char_h) +
|
||||
(y1 * char_w) + x1)
|
||||
font_data[bit_index // 8] |= 1 << (bit_index % 8)
|
||||
|
||||
return (char_w, char_h), font_data
|
||||
|
||||
def convert_image(font_prefix, filename, output_filename):
|
||||
"""Convert the given image to a text output file.
|
||||
|
||||
Args:
|
||||
font_prefix: Prefix string to attach to constants.
|
||||
filename: Input image file to read.
|
||||
output_filename: Header file to write.
|
||||
"""
|
||||
dimensions, data = generate_font_data(filename)
|
||||
|
||||
with open(output_filename, "w") as outfile:
|
||||
outfile.write("/* Font data generated from %s; do not edit.\n"
|
||||
" Please see textscreen/fonts/README for copyright\n"
|
||||
" information. */\n\n" % filename)
|
||||
outfile.write("static const uint8_t %s_font_data[] =\n{\n" %
|
||||
font_prefix)
|
||||
for index, b in enumerate(data):
|
||||
if (index % 8) == 0:
|
||||
outfile.write(" ")
|
||||
outfile.write("0x%02x," % b)
|
||||
if ((index + 1) % 8) == 0:
|
||||
outfile.write("\n")
|
||||
else:
|
||||
outfile.write(" ")
|
||||
outfile.write("};\n")
|
||||
|
||||
outfile.write("\n")
|
||||
outfile.write("static const txt_font_t %s_font =\n{\n" % font_prefix)
|
||||
outfile.write(" \"%s\", %s_font_data, %d, %d,\n" % (
|
||||
font_prefix, font_prefix,
|
||||
dimensions[0], dimensions[1]))
|
||||
outfile.write("};\n")
|
||||
|
||||
convert_image(sys.argv[1], sys.argv[2], sys.argv[3])
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
@@ -0,0 +1,524 @@
|
||||
/* Font data generated from normal.png; do not edit.
|
||||
Please see textscreen/fonts/README for copyright
|
||||
information. */
|
||||
|
||||
static const uint8_t normal_font_data[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
|
||||
0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3,
|
||||
0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x36, 0x7f, 0x7f, 0x7f,
|
||||
0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x3e, 0x7f,
|
||||
0x3e, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7,
|
||||
0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff,
|
||||
0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
|
||||
0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3,
|
||||
0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42,
|
||||
0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
|
||||
0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x78, 0x70, 0x58, 0x4c, 0x1e, 0x33,
|
||||
0x33, 0x33, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c,
|
||||
0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfc, 0xcc, 0xfc, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0e, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfe, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6,
|
||||
0xc6, 0xe6, 0xe7, 0x67, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7,
|
||||
0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x7f, 0x1f,
|
||||
0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7f, 0x7c,
|
||||
0x78, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18,
|
||||
0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfe, 0xdb, 0xdb, 0xdb, 0xde, 0xd8,
|
||||
0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x3e, 0x63, 0x06, 0x1c, 0x36, 0x63, 0x63,
|
||||
0x36, 0x1c, 0x30, 0x63, 0x3e, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18,
|
||||
0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x7f,
|
||||
0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x7f,
|
||||
0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
|
||||
0x03, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff,
|
||||
0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x1c, 0x3e,
|
||||
0x3e, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x3e, 0x3e,
|
||||
0x1c, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18,
|
||||
0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x36, 0x36, 0x7f, 0x36, 0x36,
|
||||
0x36, 0x7f, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x18, 0x3e, 0x63, 0x43, 0x03, 0x3e, 0x60,
|
||||
0x60, 0x61, 0x63, 0x3e, 0x18, 0x18, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x43, 0x63, 0x30, 0x18,
|
||||
0x0c, 0x06, 0x63, 0x61, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x6e, 0x3b,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x0c, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff,
|
||||
0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
|
||||
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18,
|
||||
0x0c, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb,
|
||||
0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x1c, 0x1e, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x60, 0x30, 0x18, 0x0c,
|
||||
0x06, 0x03, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x60, 0x60, 0x3c, 0x60,
|
||||
0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x30, 0x38, 0x3c, 0x36, 0x33, 0x7f,
|
||||
0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x60,
|
||||
0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1c, 0x06, 0x03, 0x03, 0x3f, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7f, 0x63, 0x60, 0x60, 0x30, 0x18,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x3e, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x7e, 0x60,
|
||||
0x60, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
|
||||
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
|
||||
0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06,
|
||||
0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
|
||||
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60,
|
||||
0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x63, 0x30, 0x18, 0x18,
|
||||
0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x7b, 0x7b,
|
||||
0x7b, 0x3b, 0x03, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63, 0x7f,
|
||||
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x3e, 0x66,
|
||||
0x66, 0x66, 0x66, 0x3f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x66, 0x43, 0x03, 0x03, 0x03,
|
||||
0x03, 0x43, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1f, 0x36, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x36, 0x1f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7f, 0x66, 0x46, 0x16, 0x1e, 0x16,
|
||||
0x06, 0x46, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7f, 0x66, 0x46, 0x16, 0x1e, 0x16,
|
||||
0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x66, 0x43, 0x03, 0x03, 0x7b,
|
||||
0x63, 0x63, 0x66, 0x5c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x7f, 0x63,
|
||||
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x33, 0x33, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x67, 0x66, 0x66, 0x36, 0x1e, 0x1e,
|
||||
0x36, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x46, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3,
|
||||
0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x67, 0x6f, 0x7f, 0x7b, 0x73,
|
||||
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x3e, 0x06,
|
||||
0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x6b, 0x7b, 0x3e, 0x30, 0x70, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x3e, 0x36,
|
||||
0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x63, 0x06, 0x1c, 0x30,
|
||||
0x60, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
|
||||
0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb,
|
||||
0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18,
|
||||
0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xc3, 0x61, 0x30, 0x18, 0x0c,
|
||||
0x06, 0x83, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0e, 0x1c,
|
||||
0x38, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
|
||||
0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x3e,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x07, 0x06, 0x06, 0x1e, 0x36, 0x66,
|
||||
0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x03,
|
||||
0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x38, 0x30, 0x30, 0x3c, 0x36, 0x33,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x7f,
|
||||
0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1c, 0x36, 0x26, 0x06, 0x0f, 0x06,
|
||||
0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x3e, 0x30, 0x33, 0x1e, 0x00,
|
||||
0x00, 0x00, 0x07, 0x06, 0x06, 0x36, 0x6e, 0x66,
|
||||
0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x1c, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x60, 0x60, 0x00, 0x70, 0x60, 0x60,
|
||||
0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3c, 0x00,
|
||||
0x00, 0x00, 0x07, 0x06, 0x06, 0x66, 0x36, 0x1e,
|
||||
0x1e, 0x36, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xff, 0xdb,
|
||||
0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x0f, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x3e, 0x30, 0x30, 0x78, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6e, 0x66,
|
||||
0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x06,
|
||||
0x1c, 0x30, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x08, 0x0c, 0x0c, 0x3f, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3,
|
||||
0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3,
|
||||
0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c,
|
||||
0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x7e, 0x60, 0x30, 0x1f, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x33, 0x18,
|
||||
0x0c, 0x06, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18,
|
||||
0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18,
|
||||
0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x36, 0x63,
|
||||
0x63, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x66, 0x43, 0x03, 0x03, 0x03,
|
||||
0x43, 0x66, 0x3c, 0x30, 0x60, 0x3e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x30, 0x18, 0x0c, 0x00, 0x3e, 0x63, 0x7f,
|
||||
0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x08, 0x1c, 0x36, 0x00, 0x1e, 0x30, 0x3e,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x33, 0x00, 0x00, 0x1e, 0x30, 0x3e,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x06, 0x0c, 0x18, 0x00, 0x1e, 0x30, 0x3e,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x1c, 0x36, 0x1c, 0x00, 0x1e, 0x30, 0x3e,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06,
|
||||
0x66, 0x3c, 0x30, 0x60, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x7f,
|
||||
0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x00, 0x00, 0x3e, 0x63, 0x7f,
|
||||
0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x06, 0x0c, 0x18, 0x00, 0x3e, 0x63, 0x7f,
|
||||
0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x66, 0x00, 0x00, 0x1c, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x18, 0x3c, 0x66, 0x00, 0x1c, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x06, 0x0c, 0x18, 0x00, 0x1c, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x63, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63,
|
||||
0x7f, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1c, 0x36, 0x1c, 0x00, 0x1c, 0x36, 0x63, 0x63,
|
||||
0x7f, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x0c, 0x06, 0x00, 0x7f, 0x66, 0x06, 0x3e,
|
||||
0x06, 0x06, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8,
|
||||
0x7e, 0x1b, 0x3b, 0xee, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7c, 0x36, 0x33, 0x33, 0x7f, 0x33,
|
||||
0x33, 0x33, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x00, 0x00, 0x3e, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x06, 0x0c, 0x18, 0x00, 0x3e, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x0c, 0x1e, 0x33, 0x00, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x06, 0x0c, 0x18, 0x00, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x00, 0x00, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x7e, 0x60, 0x30, 0x1e, 0x00,
|
||||
0x00, 0x63, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x63, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x18, 0x18, 0x7e, 0xc3, 0x03, 0x03, 0x03,
|
||||
0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x1c, 0x36, 0x26, 0x06, 0x0f, 0x06, 0x06,
|
||||
0x06, 0x06, 0x67, 0x3f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18,
|
||||
0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x3f, 0x66, 0x66, 0x3e, 0x46, 0x66, 0xf6,
|
||||
0x66, 0x66, 0x66, 0xcf, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x7e, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00,
|
||||
0x00, 0x18, 0x0c, 0x06, 0x00, 0x1e, 0x30, 0x3e,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x30, 0x18, 0x0c, 0x00, 0x1c, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x18, 0x0c, 0x06, 0x00, 0x3e, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x18, 0x0c, 0x06, 0x00, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x6e, 0x3b, 0x00, 0x3b, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6e, 0x3b, 0x00, 0x63, 0x67, 0x6f, 0x7f, 0x7b,
|
||||
0x73, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x7e, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x1c, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x06,
|
||||
0x03, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x03,
|
||||
0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60,
|
||||
0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0c,
|
||||
0x06, 0x73, 0xd9, 0x60, 0x30, 0xf8, 0x00, 0x00,
|
||||
0x00, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0c,
|
||||
0x66, 0x73, 0x69, 0x7c, 0x60, 0x60, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18,
|
||||
0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0x1b,
|
||||
0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c,
|
||||
0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22,
|
||||
0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22,
|
||||
0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
|
||||
0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
|
||||
0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee,
|
||||
0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6f,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6f, 0x60, 0x6f,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60, 0x6f,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6f, 0x60, 0x7f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x7f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xec,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xec, 0x0c, 0xfc,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0xec,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xef, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xef,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xec, 0x0c, 0xec,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xef, 0x00, 0xef,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfc,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xff,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b,
|
||||
0x1b, 0x1b, 0x3b, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x1b, 0x33,
|
||||
0x63, 0x63, 0x63, 0x33, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7f, 0x63, 0x63, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x7f, 0x63, 0x06, 0x0c, 0x18,
|
||||
0x0c, 0x06, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x1b, 0x1b,
|
||||
0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x3e, 0x06, 0x06, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
|
||||
0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x7f,
|
||||
0x63, 0x63, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x63, 0x36,
|
||||
0x36, 0x36, 0x36, 0x77, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x78, 0x0c, 0x18, 0x30, 0x7c, 0x66,
|
||||
0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb,
|
||||
0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xc0, 0x60, 0x7e, 0xdb, 0xdb,
|
||||
0xcf, 0x7e, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x38, 0x0c, 0x06, 0x06, 0x3e, 0x06,
|
||||
0x06, 0x06, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f,
|
||||
0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
|
||||
0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30,
|
||||
0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c,
|
||||
0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x70, 0xd8, 0xd8, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e,
|
||||
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x00,
|
||||
0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x1c, 0x36, 0x36, 0x1c, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
|
||||
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x37,
|
||||
0x36, 0x36, 0x3c, 0x38, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x1b, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x0e, 0x1b, 0x0c, 0x06, 0x13, 0x1f, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0x3e,
|
||||
0x3e, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const txt_font_t normal_font =
|
||||
{
|
||||
"normal", normal_font_data, 8, 16,
|
||||
};
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,140 @@
|
||||
/* Font data generated from small.png; do not edit.
|
||||
Please see textscreen/fonts/README for copyright
|
||||
information. */
|
||||
|
||||
static const uint8_t small_font_data[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x4e, 0x00,
|
||||
0xf6, 0xf5, 0xb1, 0x6f, 0x00, 0xea, 0x04, 0x00,
|
||||
0x00, 0xe4, 0x04, 0x00, 0x40, 0xaa, 0xe4, 0x00,
|
||||
0x40, 0xee, 0xe4, 0x00, 0x00, 0x60, 0x06, 0x00,
|
||||
0xff, 0x9f, 0xf9, 0xff, 0x00, 0x96, 0x69, 0x00,
|
||||
0xff, 0x69, 0x96, 0xff, 0xe0, 0x74, 0x75, 0x00,
|
||||
0x60, 0x69, 0x6f, 0x06, 0xc0, 0x44, 0x74, 0x03,
|
||||
0xe0, 0xaa, 0xba, 0x03, 0x22, 0x27, 0x27, 0x22,
|
||||
0x10, 0x73, 0x13, 0x00, 0x80, 0xec, 0x8c, 0x00,
|
||||
0x40, 0x4e, 0xe4, 0x04, 0xa0, 0xaa, 0xa0, 0x00,
|
||||
0xf0, 0xb9, 0xaa, 0x00, 0x16, 0x96, 0x86, 0x06,
|
||||
0x00, 0x00, 0xff, 0x00, 0x40, 0x4e, 0xe4, 0xf4,
|
||||
0x40, 0x4e, 0x44, 0x04, 0x40, 0x44, 0xe4, 0x04,
|
||||
0x20, 0xf4, 0x24, 0x00, 0x40, 0xf2, 0x42, 0x00,
|
||||
0x00, 0x10, 0x07, 0x00, 0x00, 0xf5, 0x05, 0x00,
|
||||
0x00, 0x72, 0x0f, 0x00, 0x00, 0x7f, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x20, 0x22, 0x02, 0x02,
|
||||
0x50, 0x05, 0x00, 0x00, 0x50, 0x57, 0x75, 0x05,
|
||||
0x22, 0x25, 0x54, 0x22, 0x50, 0x24, 0x12, 0x05,
|
||||
0x52, 0x52, 0x35, 0x06, 0x20, 0x02, 0x00, 0x00,
|
||||
0x40, 0x22, 0x22, 0x04, 0x10, 0x22, 0x22, 0x01,
|
||||
0x50, 0x72, 0x52, 0x00, 0x20, 0x72, 0x22, 0x00,
|
||||
0x00, 0x00, 0x20, 0x12, 0x00, 0x70, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x02, 0x40, 0x24, 0x12, 0x01,
|
||||
0x20, 0x75, 0x55, 0x02, 0x20, 0x23, 0x22, 0x07,
|
||||
0x20, 0x45, 0x12, 0x07, 0x70, 0x24, 0x54, 0x02,
|
||||
0x40, 0x56, 0x47, 0x04, 0x70, 0x31, 0x54, 0x02,
|
||||
0x60, 0x31, 0x55, 0x02, 0x70, 0x44, 0x22, 0x02,
|
||||
0x20, 0x25, 0x55, 0x02, 0x20, 0x55, 0x46, 0x03,
|
||||
0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x01,
|
||||
0x00, 0x24, 0x21, 0x04, 0x00, 0x07, 0x07, 0x00,
|
||||
0x00, 0x21, 0x24, 0x01, 0x20, 0x45, 0x02, 0x02,
|
||||
0x20, 0x55, 0x11, 0x06, 0x20, 0x55, 0x57, 0x05,
|
||||
0x30, 0x35, 0x55, 0x03, 0x20, 0x15, 0x51, 0x02,
|
||||
0x30, 0x55, 0x55, 0x03, 0x70, 0x71, 0x11, 0x07,
|
||||
0x70, 0x71, 0x11, 0x01, 0x20, 0x15, 0x55, 0x02,
|
||||
0x50, 0x75, 0x55, 0x05, 0x70, 0x22, 0x22, 0x07,
|
||||
0x40, 0x44, 0x54, 0x02, 0x50, 0x35, 0x55, 0x05,
|
||||
0x10, 0x11, 0x11, 0x07, 0x50, 0x57, 0x55, 0x05,
|
||||
0x40, 0x75, 0x57, 0x01, 0x20, 0x55, 0x55, 0x02,
|
||||
0x30, 0x55, 0x13, 0x01, 0x20, 0x55, 0x35, 0x06,
|
||||
0x30, 0x55, 0x53, 0x05, 0x20, 0x25, 0x54, 0x02,
|
||||
0x70, 0x22, 0x22, 0x02, 0x50, 0x55, 0x55, 0x07,
|
||||
0x50, 0x55, 0x55, 0x02, 0x50, 0x55, 0x75, 0x05,
|
||||
0x50, 0x25, 0x55, 0x05, 0x50, 0x25, 0x22, 0x02,
|
||||
0x70, 0x24, 0x12, 0x07, 0x60, 0x22, 0x22, 0x06,
|
||||
0x10, 0x21, 0x42, 0x04, 0x30, 0x22, 0x22, 0x03,
|
||||
0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
|
||||
0x10, 0x02, 0x00, 0x00, 0x00, 0x43, 0x56, 0x06,
|
||||
0x10, 0x31, 0x55, 0x03, 0x00, 0x16, 0x11, 0x06,
|
||||
0x40, 0x64, 0x55, 0x06, 0x00, 0x52, 0x17, 0x06,
|
||||
0x40, 0x72, 0x22, 0x02, 0x00, 0x56, 0x65, 0x34,
|
||||
0x10, 0x31, 0x55, 0x05, 0x20, 0x30, 0x22, 0x07,
|
||||
0x40, 0x60, 0x44, 0x34, 0x10, 0x51, 0x53, 0x05,
|
||||
0x20, 0x22, 0x22, 0x02, 0x00, 0x75, 0x55, 0x05,
|
||||
0x00, 0x53, 0x55, 0x05, 0x00, 0x52, 0x55, 0x02,
|
||||
0x00, 0x53, 0x35, 0x11, 0x00, 0x56, 0x65, 0x44,
|
||||
0x00, 0x16, 0x11, 0x01, 0x00, 0x16, 0x42, 0x03,
|
||||
0x20, 0x72, 0x22, 0x02, 0x00, 0x55, 0x55, 0x07,
|
||||
0x00, 0x55, 0x55, 0x02, 0x00, 0x55, 0x75, 0x05,
|
||||
0x00, 0x55, 0x52, 0x05, 0x00, 0x55, 0x65, 0x34,
|
||||
0x00, 0x47, 0x12, 0x07, 0x24, 0x12, 0x22, 0x04,
|
||||
0x22, 0x02, 0x22, 0x02, 0x21, 0x42, 0x22, 0x01,
|
||||
0xa0, 0x05, 0x00, 0x00, 0x20, 0x55, 0x75, 0x00,
|
||||
0x20, 0x15, 0x51, 0x32, 0x05, 0x55, 0x55, 0x07,
|
||||
0x12, 0x52, 0x17, 0x06, 0xa4, 0x43, 0x56, 0x06,
|
||||
0x05, 0x43, 0x56, 0x06, 0x42, 0x43, 0x56, 0x06,
|
||||
0x52, 0x42, 0x56, 0x06, 0x00, 0x16, 0x11, 0x36,
|
||||
0x52, 0x52, 0x17, 0x06, 0x05, 0x52, 0x17, 0x06,
|
||||
0x42, 0x52, 0x17, 0x06, 0x50, 0x30, 0x22, 0x07,
|
||||
0x52, 0x30, 0x22, 0x07, 0x42, 0x30, 0x22, 0x07,
|
||||
0x05, 0x52, 0x57, 0x05, 0x52, 0x52, 0x57, 0x05,
|
||||
0x24, 0x17, 0x13, 0x07, 0x00, 0xad, 0x5e, 0x0e,
|
||||
0xe0, 0xf5, 0x55, 0x0d, 0x52, 0x20, 0x55, 0x02,
|
||||
0x05, 0x52, 0x55, 0x02, 0x42, 0x52, 0x55, 0x02,
|
||||
0x52, 0x50, 0x55, 0x07, 0x42, 0x50, 0x55, 0x07,
|
||||
0x05, 0x55, 0x65, 0x34, 0x05, 0x52, 0x55, 0x02,
|
||||
0x05, 0x55, 0x55, 0x07, 0x20, 0x16, 0x61, 0x02,
|
||||
0x2c, 0x72, 0x22, 0x0f, 0x50, 0x25, 0x27, 0x02,
|
||||
0x30, 0x35, 0xd5, 0x05, 0x48, 0xe4, 0x54, 0x02,
|
||||
0x24, 0x43, 0x56, 0x06, 0x24, 0x30, 0x22, 0x07,
|
||||
0x12, 0x52, 0x55, 0x02, 0x24, 0x50, 0x55, 0x07,
|
||||
0x5a, 0x30, 0x55, 0x05, 0x5a, 0x90, 0xdb, 0x09,
|
||||
0x56, 0x0e, 0x0f, 0x00, 0x52, 0x02, 0x07, 0x00,
|
||||
0x20, 0x20, 0x51, 0x02, 0x00, 0x70, 0x11, 0x00,
|
||||
0x00, 0xe0, 0x88, 0x00, 0x11, 0x25, 0x8d, 0xc4,
|
||||
0x11, 0x25, 0xa1, 0x8e, 0x20, 0x20, 0x22, 0x02,
|
||||
0x00, 0xa0, 0xa5, 0x00, 0x00, 0x50, 0x5a, 0x00,
|
||||
0x28, 0x28, 0x28, 0x28, 0x5a, 0x5a, 0x5a, 0x5a,
|
||||
0xeb, 0xeb, 0xeb, 0xeb, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x74, 0x44, 0x44, 0x44, 0x47, 0x47, 0x44,
|
||||
0xaa, 0xba, 0xaa, 0xaa, 0x00, 0xf0, 0xaa, 0xaa,
|
||||
0x00, 0x47, 0x47, 0x44, 0xaa, 0x8b, 0xab, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x8f, 0xab, 0xaa,
|
||||
0xaa, 0x8b, 0x0f, 0x00, 0xaa, 0xfa, 0x00, 0x00,
|
||||
0x44, 0x47, 0x07, 0x00, 0x00, 0x70, 0x44, 0x44,
|
||||
0x44, 0xc4, 0x00, 0x00, 0x44, 0xf4, 0x00, 0x00,
|
||||
0x00, 0xf0, 0x44, 0x44, 0x44, 0xc4, 0x44, 0x44,
|
||||
0x00, 0xf0, 0x00, 0x00, 0x44, 0xf4, 0x44, 0x44,
|
||||
0x44, 0x4c, 0x4c, 0x44, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0x2a, 0x0e, 0x00, 0x00, 0x2e, 0xaa, 0xaa,
|
||||
0xaa, 0x0b, 0x0f, 0x00, 0x00, 0x0f, 0xab, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x0f, 0x0f, 0x00,
|
||||
0xaa, 0x0b, 0xab, 0xaa, 0x44, 0x0f, 0x0f, 0x00,
|
||||
0xaa, 0xfa, 0x00, 0x00, 0x00, 0x0f, 0x4f, 0x44,
|
||||
0x00, 0xf0, 0xaa, 0xaa, 0xaa, 0xea, 0x00, 0x00,
|
||||
0x44, 0x4c, 0x0c, 0x00, 0x00, 0x4c, 0x4c, 0x44,
|
||||
0x00, 0xe0, 0xaa, 0xaa, 0xaa, 0xfa, 0xaa, 0xaa,
|
||||
0x44, 0x4f, 0x4f, 0x44, 0x44, 0x74, 0x00, 0x00,
|
||||
0x00, 0xc0, 0x44, 0x44, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0xff, 0xff, 0x33, 0x33, 0x33, 0x33,
|
||||
0xcc, 0xcc, 0xcc, 0xcc, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0xa0, 0x55, 0x0a, 0x30, 0x35, 0x95, 0x05,
|
||||
0xf0, 0x19, 0x11, 0x01, 0x00, 0x5f, 0x55, 0x05,
|
||||
0x00, 0x17, 0x12, 0x07, 0x00, 0x5e, 0x55, 0x02,
|
||||
0x00, 0xaa, 0x2e, 0x01, 0x00, 0x5a, 0x44, 0x04,
|
||||
0x70, 0x52, 0x25, 0x07, 0x20, 0x75, 0x55, 0x02,
|
||||
0x60, 0x99, 0x66, 0x0f, 0x60, 0x21, 0x55, 0x02,
|
||||
0x00, 0xd6, 0x6b, 0x00, 0x80, 0x9f, 0xf9, 0x01,
|
||||
0x60, 0x71, 0x11, 0x06, 0x20, 0x55, 0x55, 0x05,
|
||||
0x70, 0x70, 0x70, 0x00, 0x20, 0x27, 0x70, 0x00,
|
||||
0x10, 0x42, 0x12, 0x07, 0x40, 0x12, 0x42, 0x07,
|
||||
0x80, 0x44, 0x44, 0x44, 0x44, 0x44, 0x25, 0x00,
|
||||
0x00, 0x02, 0x07, 0x02, 0xa0, 0x05, 0x5a, 0x00,
|
||||
0x52, 0x02, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00,
|
||||
0x00, 0x00, 0x02, 0x00, 0x4c, 0x54, 0x46, 0x00,
|
||||
0x57, 0x55, 0x00, 0x00, 0x43, 0x72, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const txt_font_t small_font =
|
||||
{
|
||||
"small", small_font_data, 4, 8,
|
||||
};
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TEXTSCREEN_H
|
||||
#define TEXTSCREEN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../include/doomkeys.h"
|
||||
#include "txt_main.h"
|
||||
|
||||
#include "txt_button.h"
|
||||
#include "txt_checkbox.h"
|
||||
#include "txt_conditional.h"
|
||||
#include "txt_desktop.h"
|
||||
#include "txt_dropdown.h"
|
||||
#include "txt_fileselect.h"
|
||||
#include "txt_inputbox.h"
|
||||
#include "txt_label.h"
|
||||
#include "txt_radiobutton.h"
|
||||
#include "txt_scrollpane.h"
|
||||
#include "txt_separator.h"
|
||||
#include "txt_spinctrl.h"
|
||||
#include "txt_strut.h"
|
||||
#include "txt_table.h"
|
||||
#include "txt_widget.h"
|
||||
#include "txt_window_action.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef TEXTSCREEN_H */
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_button.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
static void TXT_ButtonSizeCalc(TXT_UNCAST_ARG(button))
|
||||
{
|
||||
TXT_CAST_ARG(txt_button_t, button);
|
||||
|
||||
button->widget.w = TXT_UTF8_Strlen(button->label);
|
||||
button->widget.h = 1;
|
||||
}
|
||||
|
||||
static void TXT_ButtonDrawer(TXT_UNCAST_ARG(button))
|
||||
{
|
||||
TXT_CAST_ARG(txt_button_t, button);
|
||||
int i;
|
||||
int w;
|
||||
|
||||
w = button->widget.w;
|
||||
|
||||
TXT_SetWidgetBG(button);
|
||||
|
||||
TXT_DrawString(button->label);
|
||||
|
||||
for (i = TXT_UTF8_Strlen(button->label); i < w; ++i)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_ButtonDestructor(TXT_UNCAST_ARG(button))
|
||||
{
|
||||
TXT_CAST_ARG(txt_button_t, button);
|
||||
|
||||
free(button->label);
|
||||
}
|
||||
|
||||
static int TXT_ButtonKeyPress(TXT_UNCAST_ARG(button), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_button_t, button);
|
||||
|
||||
if (key == KEY_ENTER)
|
||||
{
|
||||
TXT_EmitSignal(button, "pressed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TXT_ButtonMousePress(TXT_UNCAST_ARG(button), int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_button_t, button);
|
||||
|
||||
if (b == TXT_MOUSE_LEFT)
|
||||
{
|
||||
// Equivalent to pressing enter
|
||||
|
||||
TXT_ButtonKeyPress(button, KEY_ENTER);
|
||||
}
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_button_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_ButtonSizeCalc,
|
||||
TXT_ButtonDrawer,
|
||||
TXT_ButtonKeyPress,
|
||||
TXT_ButtonDestructor,
|
||||
TXT_ButtonMousePress,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void TXT_SetButtonLabel(txt_button_t *button, const char *label)
|
||||
{
|
||||
free(button->label);
|
||||
button->label = strdup(label);
|
||||
}
|
||||
|
||||
txt_button_t *TXT_NewButton(const char *label)
|
||||
{
|
||||
txt_button_t *button;
|
||||
|
||||
button = malloc(sizeof(txt_button_t));
|
||||
|
||||
TXT_InitWidget(button, &txt_button_class);
|
||||
button->label = strdup(label);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
// Button with a callback set automatically
|
||||
|
||||
txt_button_t *TXT_NewButton2(const char *label, TxtWidgetSignalFunc func,
|
||||
void *user_data)
|
||||
{
|
||||
txt_button_t *button;
|
||||
|
||||
button = TXT_NewButton(label);
|
||||
|
||||
TXT_SignalConnect(button, "pressed", func, user_data);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_BUTTON_H
|
||||
#define TXT_BUTTON_H
|
||||
|
||||
/**
|
||||
* @file txt_button.h
|
||||
*
|
||||
* Button widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Button widget.
|
||||
*
|
||||
* A button is a widget that can be selected to perform some action.
|
||||
* When a button is pressed, it emits the "pressed" signal.
|
||||
*/
|
||||
|
||||
typedef struct txt_button_s txt_button_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_button_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
char *label;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new button widget.
|
||||
*
|
||||
* @param label The label to use on the new button (UTF-8 format).
|
||||
* @return Pointer to the new button widget.
|
||||
*/
|
||||
|
||||
txt_button_t *TXT_NewButton(const char *label);
|
||||
|
||||
/**
|
||||
* Create a new button widget, binding the "pressed" signal to a
|
||||
* specified callback function.
|
||||
*
|
||||
* @param label The label to use on the new button (UTF-8 format).
|
||||
* @param func The callback function to invoke.
|
||||
* @param user_data User-specified pointer to pass to the callback.
|
||||
* @return Pointer to the new button widget.
|
||||
*/
|
||||
|
||||
txt_button_t *TXT_NewButton2(const char *label, TxtWidgetSignalFunc func,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* Change the label used on a button.
|
||||
*
|
||||
* @param button The button.
|
||||
* @param label The new label (UTF-8 format).
|
||||
*/
|
||||
|
||||
void TXT_SetButtonLabel(txt_button_t *button, const char *label);
|
||||
|
||||
#endif /* #ifndef TXT_BUTTON_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_checkbox.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
static void TXT_CheckBoxSizeCalc(TXT_UNCAST_ARG(checkbox))
|
||||
{
|
||||
TXT_CAST_ARG(txt_checkbox_t, checkbox);
|
||||
|
||||
// Minimum width is the string length + right-side space for padding
|
||||
|
||||
checkbox->widget.w = TXT_UTF8_Strlen(checkbox->label) + 5;
|
||||
checkbox->widget.h = 1;
|
||||
}
|
||||
|
||||
static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox))
|
||||
{
|
||||
TXT_CAST_ARG(txt_checkbox_t, checkbox);
|
||||
txt_saved_colors_t colors;
|
||||
int i;
|
||||
int w;
|
||||
|
||||
w = checkbox->widget.w;
|
||||
|
||||
TXT_SaveColors(&colors);
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
TXT_DrawString("(");
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
|
||||
|
||||
if ((*checkbox->variable != 0) ^ checkbox->inverted)
|
||||
{
|
||||
TXT_DrawCodePageString("\x07");
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
|
||||
TXT_DrawString(") ");
|
||||
|
||||
TXT_RestoreColors(&colors);
|
||||
TXT_SetWidgetBG(checkbox);
|
||||
TXT_DrawString(checkbox->label);
|
||||
|
||||
for (i = TXT_UTF8_Strlen(checkbox->label); i < w-4; ++i)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_CheckBoxDestructor(TXT_UNCAST_ARG(checkbox))
|
||||
{
|
||||
TXT_CAST_ARG(txt_checkbox_t, checkbox);
|
||||
|
||||
free(checkbox->label);
|
||||
}
|
||||
|
||||
static int TXT_CheckBoxKeyPress(TXT_UNCAST_ARG(checkbox), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_checkbox_t, checkbox);
|
||||
|
||||
if (key == KEY_ENTER || key == ' ')
|
||||
{
|
||||
*checkbox->variable = !*checkbox->variable;
|
||||
TXT_EmitSignal(checkbox, "changed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TXT_CheckBoxMousePress(TXT_UNCAST_ARG(checkbox), int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_checkbox_t, checkbox);
|
||||
|
||||
if (b == TXT_MOUSE_LEFT)
|
||||
{
|
||||
// Equivalent to pressing enter
|
||||
|
||||
TXT_CheckBoxKeyPress(checkbox, KEY_ENTER);
|
||||
}
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_checkbox_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_CheckBoxSizeCalc,
|
||||
TXT_CheckBoxDrawer,
|
||||
TXT_CheckBoxKeyPress,
|
||||
TXT_CheckBoxDestructor,
|
||||
TXT_CheckBoxMousePress,
|
||||
NULL,
|
||||
};
|
||||
|
||||
txt_checkbox_t *TXT_NewCheckBox(const char *label, int *variable)
|
||||
{
|
||||
txt_checkbox_t *checkbox;
|
||||
|
||||
checkbox = malloc(sizeof(txt_checkbox_t));
|
||||
|
||||
TXT_InitWidget(checkbox, &txt_checkbox_class);
|
||||
checkbox->label = strdup(label);
|
||||
checkbox->variable = variable;
|
||||
checkbox->inverted = 0;
|
||||
|
||||
return checkbox;
|
||||
}
|
||||
|
||||
txt_checkbox_t *TXT_NewInvertedCheckBox(const char *label, int *variable)
|
||||
{
|
||||
txt_checkbox_t *result;
|
||||
|
||||
result = TXT_NewCheckBox(label, variable);
|
||||
result->inverted = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_CHECKBOX_H
|
||||
#define TXT_CHECKBOX_H
|
||||
|
||||
/**
|
||||
* @file txt_checkbox.h
|
||||
*
|
||||
* Checkbox widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checkbox widget.
|
||||
*
|
||||
* A checkbox is used to control boolean values that may be either on
|
||||
* or off. The widget has a label that is displayed to the right of
|
||||
* the checkbox indicator. The widget tracks an integer variable;
|
||||
* if the variable is non-zero, the checkbox is checked, while if it
|
||||
* is zero, the checkbox is unchecked. It is also possible to
|
||||
* create "inverted" checkboxes where this logic is reversed.
|
||||
*
|
||||
* When a checkbox is changed, it emits the "changed" signal.
|
||||
*/
|
||||
|
||||
typedef struct txt_checkbox_s txt_checkbox_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_checkbox_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
char *label;
|
||||
int *variable;
|
||||
int inverted;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new checkbox.
|
||||
*
|
||||
* @param label The label for the new checkbox (UTF-8 format).
|
||||
* @param variable Pointer to the variable containing this checkbox's
|
||||
* value.
|
||||
* @return Pointer to the new checkbox.
|
||||
*/
|
||||
|
||||
txt_checkbox_t *TXT_NewCheckBox(const char *label, int *variable);
|
||||
|
||||
/**
|
||||
* Create a new inverted checkbox.
|
||||
*
|
||||
* An inverted checkbox displays the opposite of a normal checkbox;
|
||||
* where it would be checked, it appears unchecked, and vice-versa.
|
||||
*
|
||||
* @param label The label for the new checkbox (UTF-8 format).
|
||||
* @param variable Pointer to the variable containing this checkbox's
|
||||
* value.
|
||||
* @return Pointer to the new checkbox.
|
||||
*/
|
||||
|
||||
txt_checkbox_t *TXT_NewInvertedCheckBox(const char *label, int *variable);
|
||||
|
||||
#endif /* #ifndef TXT_CHECKBOX_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
//
|
||||
// Copyright(C) 2016 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "txt_conditional.h"
|
||||
#include "txt_strut.h"
|
||||
|
||||
struct txt_conditional_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
int *var;
|
||||
int expected_value;
|
||||
txt_widget_t *child;
|
||||
};
|
||||
|
||||
static int ConditionTrue(txt_conditional_t *conditional)
|
||||
{
|
||||
return *conditional->var == conditional->expected_value;
|
||||
}
|
||||
|
||||
static int TXT_CondSelectable(TXT_UNCAST_ARG(conditional))
|
||||
{
|
||||
TXT_CAST_ARG(txt_conditional_t, conditional);
|
||||
return ConditionTrue(conditional)
|
||||
&& TXT_SelectableWidget(conditional->child);
|
||||
}
|
||||
|
||||
static void TXT_CondSizeCalc(TXT_UNCAST_ARG(conditional))
|
||||
{
|
||||
TXT_CAST_ARG(txt_conditional_t, conditional);
|
||||
|
||||
if (!ConditionTrue(conditional))
|
||||
{
|
||||
conditional->widget.w = 0;
|
||||
conditional->widget.h = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_CalcWidgetSize(conditional->child);
|
||||
conditional->widget.w = conditional->child->w;
|
||||
conditional->widget.h = conditional->child->h;
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_CondLayout(TXT_UNCAST_ARG(conditional))
|
||||
{
|
||||
TXT_CAST_ARG(txt_conditional_t, conditional);
|
||||
|
||||
if (ConditionTrue(conditional))
|
||||
{
|
||||
conditional->child->x = conditional->widget.x;
|
||||
conditional->child->y = conditional->widget.y;
|
||||
TXT_LayoutWidget(conditional->child);
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_CondDrawer(TXT_UNCAST_ARG(conditional))
|
||||
{
|
||||
TXT_CAST_ARG(txt_conditional_t, conditional);
|
||||
|
||||
if (ConditionTrue(conditional))
|
||||
{
|
||||
TXT_DrawWidget(conditional->child);
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_CondDestructor(TXT_UNCAST_ARG(conditional))
|
||||
{
|
||||
TXT_CAST_ARG(txt_conditional_t, conditional);
|
||||
TXT_DestroyWidget(conditional->child);
|
||||
}
|
||||
|
||||
static void TXT_CondFocused(TXT_UNCAST_ARG(conditional), int focused)
|
||||
{
|
||||
TXT_CAST_ARG(txt_conditional_t, conditional);
|
||||
|
||||
if (ConditionTrue(conditional))
|
||||
{
|
||||
TXT_SetWidgetFocus(conditional->child, focused);
|
||||
}
|
||||
}
|
||||
|
||||
static int TXT_CondKeyPress(TXT_UNCAST_ARG(conditional), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_conditional_t, conditional);
|
||||
|
||||
if (ConditionTrue(conditional))
|
||||
{
|
||||
return TXT_WidgetKeyPress(conditional->child, key);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TXT_CondMousePress(TXT_UNCAST_ARG(conditional),
|
||||
int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_conditional_t, conditional);
|
||||
|
||||
if (ConditionTrue(conditional))
|
||||
{
|
||||
TXT_WidgetMousePress(conditional->child, x, y, b);
|
||||
}
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_conditional_class =
|
||||
{
|
||||
TXT_CondSelectable,
|
||||
TXT_CondSizeCalc,
|
||||
TXT_CondDrawer,
|
||||
TXT_CondKeyPress,
|
||||
TXT_CondDestructor,
|
||||
TXT_CondMousePress,
|
||||
TXT_CondLayout,
|
||||
TXT_CondFocused,
|
||||
};
|
||||
|
||||
txt_conditional_t *TXT_NewConditional(int *var, int expected_value,
|
||||
TXT_UNCAST_ARG(child))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, child);
|
||||
txt_conditional_t *conditional;
|
||||
|
||||
conditional = malloc(sizeof(txt_conditional_t));
|
||||
|
||||
TXT_InitWidget(conditional, &txt_conditional_class);
|
||||
conditional->var = var;
|
||||
conditional->expected_value = expected_value;
|
||||
conditional->child = child;
|
||||
|
||||
child->parent = &conditional->widget;
|
||||
|
||||
return conditional;
|
||||
}
|
||||
|
||||
// "Static" conditional that returns an empty strut if the given static
|
||||
// value is false. Kind of like a conditional but we only evaluate it at
|
||||
// creation time.
|
||||
txt_widget_t *TXT_If(int conditional, TXT_UNCAST_ARG(child))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, child);
|
||||
|
||||
if (conditional)
|
||||
{
|
||||
return child;
|
||||
}
|
||||
else
|
||||
{
|
||||
txt_strut_t *nullwidget;
|
||||
TXT_DestroyWidget(child);
|
||||
nullwidget = TXT_NewStrut(0, 0);
|
||||
return &nullwidget->widget;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Copyright(C) 2016 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_CONDITIONAL_H
|
||||
#define TXT_CONDITIONAL_H
|
||||
|
||||
/**
|
||||
* @file txt_conditional.h
|
||||
*
|
||||
* Conditional widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Conditional widget.
|
||||
*
|
||||
* A conditional widget contains another widget, and conditionally
|
||||
* shows or hides it based on the value of a variable.
|
||||
*/
|
||||
|
||||
typedef struct txt_conditional_s txt_conditional_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
/**
|
||||
* Create a new conditional widget.
|
||||
*
|
||||
* @param var The variable to check.
|
||||
* @param expected_value If the variable has this value, the widget is shown.
|
||||
* @param child The inner widget to show or hide.
|
||||
* @return Pointer to the new conditional widget.
|
||||
*/
|
||||
|
||||
txt_conditional_t *TXT_NewConditional(int *var, int expected_value,
|
||||
TXT_UNCAST_ARG(child));
|
||||
|
||||
/**
|
||||
* Return the given child widget if the given boolean condition is true.
|
||||
*
|
||||
* If the condition is not true, the child widget is destroyed and a dummy
|
||||
* "null" widget is returned that shows nothing.
|
||||
*
|
||||
* @param condition Boolean condition - true or false value.
|
||||
* @param child Widget to conditionally return.
|
||||
* @return Either child (if condition is true) or a null
|
||||
* widget.
|
||||
*/
|
||||
|
||||
txt_widget_t *TXT_If(int condition, TXT_UNCAST_ARG(child));
|
||||
|
||||
#endif /* #ifndef TXT_CONDITIONAL_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,413 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_desktop.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_separator.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
#define HELP_KEY KEY_F1
|
||||
#define MAXWINDOWS 128
|
||||
|
||||
static char *desktop_title;
|
||||
static txt_window_t *all_windows[MAXWINDOWS];
|
||||
static int num_windows = 0;
|
||||
static int main_loop_running = 0;
|
||||
|
||||
static TxtIdleCallback periodic_callback = NULL;
|
||||
static void *periodic_callback_data;
|
||||
static unsigned int periodic_callback_period;
|
||||
|
||||
static char *help_label;
|
||||
|
||||
void TXT_AddDesktopWindow(txt_window_t *win)
|
||||
{
|
||||
// Previously-top window loses focus:
|
||||
|
||||
if (num_windows > 0)
|
||||
{
|
||||
TXT_SetWindowFocus(all_windows[num_windows - 1], 0);
|
||||
}
|
||||
|
||||
all_windows[num_windows] = win;
|
||||
++num_windows;
|
||||
|
||||
// New window gains focus:
|
||||
|
||||
TXT_SetWindowFocus(win, 1);
|
||||
}
|
||||
|
||||
void TXT_RemoveDesktopWindow(txt_window_t *win)
|
||||
{
|
||||
int from, to;
|
||||
|
||||
// Window must lose focus if it's being removed:
|
||||
|
||||
TXT_SetWindowFocus(win, 0);
|
||||
|
||||
for (from=0, to=0; from<num_windows; ++from)
|
||||
{
|
||||
if (all_windows[from] != win)
|
||||
{
|
||||
all_windows[to] = all_windows[from];
|
||||
++to;
|
||||
}
|
||||
}
|
||||
|
||||
num_windows = to;
|
||||
|
||||
// Top window gains focus:
|
||||
|
||||
if (num_windows > 0)
|
||||
{
|
||||
TXT_SetWindowFocus(all_windows[num_windows - 1], 1);
|
||||
}
|
||||
}
|
||||
|
||||
txt_window_t *TXT_GetActiveWindow(void)
|
||||
{
|
||||
if (num_windows == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return all_windows[num_windows - 1];
|
||||
}
|
||||
|
||||
int TXT_RaiseWindow(txt_window_t *window)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_windows - 1; ++i)
|
||||
{
|
||||
if (all_windows[i] == window)
|
||||
{
|
||||
all_windows[i] = all_windows[i + 1];
|
||||
all_windows[i + 1] = window;
|
||||
|
||||
if (i == num_windows - 2)
|
||||
{
|
||||
TXT_SetWindowFocus(all_windows[i], 0);
|
||||
TXT_SetWindowFocus(window, 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Window not in the list, or at the end of the list (top) already.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TXT_LowerWindow(txt_window_t *window)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_windows - 1; ++i)
|
||||
{
|
||||
if (all_windows[i + 1] == window)
|
||||
{
|
||||
all_windows[i + 1] = all_windows[i];
|
||||
all_windows[i] = window;
|
||||
|
||||
if (i == num_windows - 2)
|
||||
{
|
||||
TXT_SetWindowFocus(window, 0);
|
||||
TXT_SetWindowFocus(all_windows[i + 1], 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Window not in the list, or at the start of the list (bottom) already.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DrawDesktopBackground(const char *title, const char* title_help)
|
||||
{
|
||||
int i;
|
||||
unsigned char *screendata;
|
||||
unsigned char *p;
|
||||
|
||||
screendata = TXT_GetScreenData();
|
||||
|
||||
// Fill the screen with gradient characters
|
||||
|
||||
p = screendata;
|
||||
|
||||
for (i=0; i<TXT_SCREEN_W * TXT_SCREEN_H; ++i)
|
||||
{
|
||||
*p++ = 0xb1;
|
||||
*p++ = TXT_COLOR_GREY | (TXT_COLOR_BLUE << 4);
|
||||
}
|
||||
|
||||
// Draw the top and bottom banners
|
||||
|
||||
p = screendata;
|
||||
|
||||
for (i = 0; i<TXT_SCREEN_W; ++i)
|
||||
{
|
||||
*p++ = ' ';
|
||||
*p++ = TXT_COLOR_BLACK | (TXT_COLOR_GREY << 4);
|
||||
}
|
||||
|
||||
p = screendata + (TXT_SCREEN_H - 1) * TXT_SCREEN_W * 2;
|
||||
|
||||
for (i = 0; i<TXT_SCREEN_W; ++i)
|
||||
{
|
||||
*p++ = ' ';
|
||||
*p++ = TXT_COLOR_BLACK | (TXT_COLOR_GREY << 4);
|
||||
}
|
||||
|
||||
// Print the title
|
||||
|
||||
TXT_GotoXY(0, 0);
|
||||
TXT_FGColor(TXT_COLOR_BLACK);
|
||||
TXT_BGColor(TXT_COLOR_GREY, 0);
|
||||
|
||||
TXT_PutChar(' ');
|
||||
TXT_Puts(title);
|
||||
|
||||
// Help Text on bottom banner
|
||||
|
||||
TXT_GotoXY(0, 24);
|
||||
TXT_FGColor(TXT_COLOR_DARK_GREY);
|
||||
TXT_BGColor(TXT_COLOR_GREY, 0);
|
||||
|
||||
TXT_DrawString(" ");
|
||||
TXT_DrawString(title_help);
|
||||
}
|
||||
|
||||
static void DrawHelpIndicator(void)
|
||||
{
|
||||
char keybuf[10];
|
||||
int fgcolor;
|
||||
int x, y;
|
||||
|
||||
TXT_GetKeyDescription(HELP_KEY, keybuf, sizeof(keybuf));
|
||||
|
||||
TXT_GetMousePosition(&x, &y);
|
||||
|
||||
if (y == 0 && x >= TXT_SCREEN_W - 9)
|
||||
{
|
||||
fgcolor = TXT_COLOR_GREY;
|
||||
TXT_BGColor(TXT_COLOR_BLACK, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fgcolor = TXT_COLOR_BLACK;
|
||||
TXT_BGColor(TXT_COLOR_GREY, 0);
|
||||
}
|
||||
|
||||
TXT_GotoXY(TXT_SCREEN_W - 9, 0);
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
|
||||
TXT_DrawString(" ");
|
||||
TXT_DrawString(keybuf);
|
||||
|
||||
TXT_FGColor(fgcolor);
|
||||
TXT_DrawString("=Help ");
|
||||
}
|
||||
|
||||
void TXT_DrawHelpLabel(const char* title)
|
||||
{
|
||||
free(help_label);
|
||||
help_label = strdup(title);
|
||||
}
|
||||
|
||||
void TXT_SetDesktopTitle(const char *title)
|
||||
{
|
||||
free(desktop_title);
|
||||
desktop_title = strdup(title);
|
||||
TXT_SetWindowTitle(title);
|
||||
}
|
||||
|
||||
void TXT_DrawDesktop(void)
|
||||
{
|
||||
txt_window_t *active_window;
|
||||
const char *title;
|
||||
const char* title_help;
|
||||
int i;
|
||||
|
||||
TXT_InitClipArea();
|
||||
|
||||
if (desktop_title == NULL)
|
||||
title = "";
|
||||
else
|
||||
title = desktop_title;
|
||||
|
||||
if (help_label == NULL)
|
||||
title_help = "";
|
||||
else
|
||||
title_help = help_label;
|
||||
|
||||
DrawDesktopBackground(title, title_help);
|
||||
|
||||
active_window = TXT_GetActiveWindow();
|
||||
if (active_window != NULL && active_window->help_url != NULL)
|
||||
{
|
||||
DrawHelpIndicator();
|
||||
}
|
||||
|
||||
for (i=0; i<num_windows; ++i)
|
||||
{
|
||||
TXT_DrawWindow(all_windows[i]);
|
||||
}
|
||||
|
||||
TXT_UpdateScreen();
|
||||
}
|
||||
|
||||
// Fallback function to handle key/mouse events that are not handled by
|
||||
// the active window.
|
||||
static void DesktopInputEvent(int c)
|
||||
{
|
||||
txt_window_t *active_window;
|
||||
int x, y;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case TXT_MOUSE_LEFT:
|
||||
TXT_GetMousePosition(&x, &y);
|
||||
|
||||
// Clicking the top-right of the screen is equivalent
|
||||
// to pressing the help key.
|
||||
if (y == 0 && x >= TXT_SCREEN_W - 9)
|
||||
{
|
||||
DesktopInputEvent(HELP_KEY);
|
||||
}
|
||||
break;
|
||||
|
||||
case HELP_KEY:
|
||||
active_window = TXT_GetActiveWindow();
|
||||
if (active_window != NULL)
|
||||
{
|
||||
TXT_OpenWindowHelpURL(active_window);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void TXT_DispatchEvents(void)
|
||||
{
|
||||
txt_window_t *active_window;
|
||||
int c;
|
||||
|
||||
while ((c = TXT_GetChar()) > 0)
|
||||
{
|
||||
active_window = TXT_GetActiveWindow();
|
||||
|
||||
if (active_window != NULL && !TXT_WindowKeyPress(active_window, c))
|
||||
{
|
||||
DesktopInputEvent(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TXT_ExitMainLoop(void)
|
||||
{
|
||||
main_loop_running = 0;
|
||||
}
|
||||
|
||||
void TXT_DrawASCIITable(void)
|
||||
{
|
||||
unsigned char *screendata;
|
||||
char buf[10];
|
||||
int x, y;
|
||||
int n;
|
||||
|
||||
screendata = TXT_GetScreenData();
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
|
||||
TXT_BGColor(TXT_COLOR_BLACK, 0);
|
||||
|
||||
for (y=0; y<16; ++y)
|
||||
{
|
||||
for (x=0; x<16; ++x)
|
||||
{
|
||||
n = y * 16 + x;
|
||||
|
||||
TXT_GotoXY(x * 5, y);
|
||||
TXT_snprintf(buf, sizeof(buf), "%02x ", n);
|
||||
TXT_Puts(buf);
|
||||
|
||||
// Write the character directly to the screen memory buffer:
|
||||
|
||||
screendata[(y * TXT_SCREEN_W + x * 5 + 3) * 2] = n;
|
||||
}
|
||||
}
|
||||
|
||||
TXT_UpdateScreen();
|
||||
}
|
||||
|
||||
void TXT_SetPeriodicCallback(TxtIdleCallback callback,
|
||||
void *user_data,
|
||||
unsigned int period)
|
||||
{
|
||||
periodic_callback = callback;
|
||||
periodic_callback_data = user_data;
|
||||
periodic_callback_period = period;
|
||||
}
|
||||
|
||||
void TXT_GUIMainLoop(void)
|
||||
{
|
||||
main_loop_running = 1;
|
||||
|
||||
while (main_loop_running)
|
||||
{
|
||||
TXT_DispatchEvents();
|
||||
|
||||
// After the last window is closed, exit the loop
|
||||
|
||||
if (num_windows <= 0)
|
||||
{
|
||||
TXT_ExitMainLoop();
|
||||
continue;
|
||||
}
|
||||
|
||||
TXT_DrawDesktop();
|
||||
// TXT_DrawASCIITable();
|
||||
|
||||
if (periodic_callback == NULL)
|
||||
{
|
||||
TXT_Sleep(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_Sleep(periodic_callback_period);
|
||||
|
||||
periodic_callback(periodic_callback_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_DESKTOP_H
|
||||
#define TXT_DESKTOP_H
|
||||
|
||||
/**
|
||||
* @file txt_desktop.h
|
||||
*
|
||||
* Textscreen desktop.
|
||||
*/
|
||||
|
||||
#include "txt_window.h"
|
||||
|
||||
typedef void (*TxtIdleCallback)(void *user_data);
|
||||
|
||||
void TXT_AddDesktopWindow(txt_window_t *win);
|
||||
void TXT_RemoveDesktopWindow(txt_window_t *win);
|
||||
void TXT_DrawDesktop(void);
|
||||
void TXT_DispatchEvents(void);
|
||||
void TXT_DrawWindow(txt_window_t *window);
|
||||
void TXT_SetWindowFocus(txt_window_t *window, int focused);
|
||||
int TXT_WindowKeyPress(txt_window_t *window, int c);
|
||||
|
||||
/**
|
||||
* Set the title displayed at the top of the screen.
|
||||
*
|
||||
* @param title The title to display (UTF-8 format).
|
||||
*/
|
||||
|
||||
void TXT_SetDesktopTitle(const char *title);
|
||||
|
||||
/**
|
||||
* Set the help title displayed at the bottom of the screen.
|
||||
*
|
||||
* @param title The title to display (UTF-8 format).
|
||||
*/
|
||||
|
||||
void TXT_DrawHelpLabel(const char* title);
|
||||
|
||||
/**
|
||||
* Exit the currently-running main loop and return from the
|
||||
* @ref TXT_GUIMainLoop function.
|
||||
*/
|
||||
|
||||
void TXT_ExitMainLoop(void);
|
||||
|
||||
/**
|
||||
* Start the main event loop. At least one window must have been
|
||||
* opened prior to running this function. When no windows are left
|
||||
* open, the event loop exits.
|
||||
*
|
||||
* It is possible to trigger an exit from this function using the
|
||||
* @ref TXT_ExitMainLoop function.
|
||||
*/
|
||||
|
||||
void TXT_GUIMainLoop(void);
|
||||
|
||||
/**
|
||||
* Get the top window on the desktop that is currently receiving
|
||||
* inputs.
|
||||
*
|
||||
* @return The active window, or NULL if no windows are present.
|
||||
*/
|
||||
|
||||
txt_window_t *TXT_GetActiveWindow(void);
|
||||
|
||||
/**
|
||||
* Set a callback function to be invoked periodically by the main
|
||||
* loop code.
|
||||
*
|
||||
* @param callback The callback to invoke, or NULL to cancel
|
||||
* an existing callback.
|
||||
* @param user_data Extra data to pass to the callback.
|
||||
* @param period Maximum time between invoking each callback.
|
||||
* eg. a value of 200 will cause the callback
|
||||
* to be invoked at least once every 200ms.
|
||||
*/
|
||||
|
||||
void TXT_SetPeriodicCallback(TxtIdleCallback callback,
|
||||
void *user_data,
|
||||
unsigned int period);
|
||||
|
||||
/**
|
||||
* Raise the z-position of the given window relative to other windows.
|
||||
*
|
||||
* @param window The window to raise.
|
||||
* @return Non-zero if the window was raised successfully,
|
||||
* or zero if the window could not be raised further.
|
||||
*/
|
||||
|
||||
int TXT_RaiseWindow(txt_window_t *window);
|
||||
|
||||
/**
|
||||
* Lower the z-position of the given window relative to other windows.
|
||||
*
|
||||
* @param window The window to make inactive.
|
||||
* @return Non-zero if the window was lowered successfully,
|
||||
* or zero if the window could not be lowered further.
|
||||
*/
|
||||
|
||||
int TXT_LowerWindow(txt_window_t *window);
|
||||
|
||||
#endif /* #ifndef TXT_DESKTOP_H */
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_button.h"
|
||||
#include "txt_dropdown.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
txt_window_t *window;
|
||||
txt_dropdown_list_t *list;
|
||||
int item;
|
||||
} callback_data_t;
|
||||
|
||||
// Check if the selected value for a list is valid
|
||||
|
||||
static int ValidSelection(txt_dropdown_list_t *list)
|
||||
{
|
||||
return *list->variable >= 0 && *list->variable < list->num_values;
|
||||
}
|
||||
|
||||
// Calculate the Y position for the selector window
|
||||
|
||||
static int SelectorWindowY(txt_dropdown_list_t *list)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (ValidSelection(list))
|
||||
{
|
||||
result = list->widget.y - 1 - *list->variable;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = list->widget.y - 1 - (list->num_values / 2);
|
||||
}
|
||||
|
||||
// Keep dropdown inside the screen.
|
||||
|
||||
if (result < 1)
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
else if (result + list->num_values > (TXT_SCREEN_H - 3))
|
||||
{
|
||||
result = TXT_SCREEN_H - list->num_values - 3;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Called when a button in the selector window is pressed
|
||||
|
||||
static void ItemSelected(TXT_UNCAST_ARG(button), TXT_UNCAST_ARG(callback_data))
|
||||
{
|
||||
TXT_CAST_ARG(callback_data_t, callback_data);
|
||||
|
||||
// Set the variable
|
||||
|
||||
*callback_data->list->variable = callback_data->item;
|
||||
|
||||
TXT_EmitSignal(callback_data->list, "changed");
|
||||
|
||||
// Close the window
|
||||
|
||||
TXT_CloseWindow(callback_data->window);
|
||||
}
|
||||
|
||||
// Free callback data when the window is closed
|
||||
|
||||
static void FreeCallbackData(TXT_UNCAST_ARG(list),
|
||||
TXT_UNCAST_ARG(callback_data))
|
||||
{
|
||||
TXT_CAST_ARG(callback_data_t, callback_data);
|
||||
|
||||
free(callback_data);
|
||||
}
|
||||
|
||||
// Catch presses of escape and close the window.
|
||||
|
||||
static int SelectorWindowListener(txt_window_t *window, int key, void *user_data)
|
||||
{
|
||||
if (key == KEY_ESCAPE)
|
||||
{
|
||||
TXT_CloseWindow(window);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SelectorMouseListener(txt_window_t *window, int x, int y, int b,
|
||||
void *unused)
|
||||
{
|
||||
txt_widget_t *win;
|
||||
|
||||
win = (txt_widget_t *) window;
|
||||
|
||||
if (x < win->x || x > win->x + win->w || y < win->y || y > win->y + win->h)
|
||||
{
|
||||
TXT_CloseWindow(window);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Open the dropdown list window to select an item
|
||||
|
||||
static void OpenSelectorWindow(txt_dropdown_list_t *list)
|
||||
{
|
||||
txt_window_t *window;
|
||||
int i;
|
||||
|
||||
// Open a simple window with no title bar or action buttons.
|
||||
|
||||
window = TXT_NewWindow(NULL);
|
||||
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL);
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_CENTER, NULL);
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL);
|
||||
|
||||
// Position the window so that the currently selected item appears
|
||||
// over the top of the list widget.
|
||||
|
||||
TXT_SetWindowPosition(window, TXT_HORIZ_LEFT, TXT_VERT_TOP,
|
||||
list->widget.x - 2, SelectorWindowY(list));
|
||||
|
||||
// Add a button to the window for each option in the list.
|
||||
|
||||
for (i=0; i<list->num_values; ++i)
|
||||
{
|
||||
txt_button_t *button;
|
||||
callback_data_t *data;
|
||||
|
||||
button = TXT_NewButton(list->values[i]);
|
||||
|
||||
TXT_AddWidget(window, button);
|
||||
|
||||
// Callback struct
|
||||
|
||||
data = malloc(sizeof(callback_data_t));
|
||||
data->list = list;
|
||||
data->window = window;
|
||||
data->item = i;
|
||||
|
||||
// When the button is pressed, invoke the button press callback
|
||||
|
||||
TXT_SignalConnect(button, "pressed", ItemSelected, data);
|
||||
|
||||
// When the window is closed, free back the callback struct
|
||||
|
||||
TXT_SignalConnect(window, "closed", FreeCallbackData, data);
|
||||
|
||||
// Is this the currently-selected value? If so, select the button
|
||||
// in the window as the default.
|
||||
|
||||
if (i == *list->variable)
|
||||
{
|
||||
TXT_SelectWidget(window, button);
|
||||
}
|
||||
}
|
||||
|
||||
// Catch presses of escape in this window and close it.
|
||||
|
||||
TXT_SetKeyListener(window, SelectorWindowListener, NULL);
|
||||
TXT_SetMouseListener(window, SelectorMouseListener, NULL);
|
||||
}
|
||||
|
||||
static int DropdownListWidth(txt_dropdown_list_t *list)
|
||||
{
|
||||
int i;
|
||||
int result;
|
||||
|
||||
// Find the maximum string width
|
||||
|
||||
result = 0;
|
||||
|
||||
for (i=0; i<list->num_values; ++i)
|
||||
{
|
||||
int w = TXT_UTF8_Strlen(list->values[i]);
|
||||
if (w > result)
|
||||
{
|
||||
result = w;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void TXT_DropdownListSizeCalc(TXT_UNCAST_ARG(list))
|
||||
{
|
||||
TXT_CAST_ARG(txt_dropdown_list_t, list);
|
||||
|
||||
list->widget.w = DropdownListWidth(list);
|
||||
list->widget.h = 1;
|
||||
}
|
||||
|
||||
static void TXT_DropdownListDrawer(TXT_UNCAST_ARG(list))
|
||||
{
|
||||
TXT_CAST_ARG(txt_dropdown_list_t, list);
|
||||
unsigned int i;
|
||||
const char *str;
|
||||
|
||||
// Set bg/fg text colors.
|
||||
|
||||
TXT_SetWidgetBG(list);
|
||||
|
||||
// Select a string to draw from the list, if the current value is
|
||||
// in range. Otherwise fall back to a default.
|
||||
|
||||
if (ValidSelection(list))
|
||||
{
|
||||
str = list->values[*list->variable];
|
||||
}
|
||||
else
|
||||
{
|
||||
str = "???";
|
||||
}
|
||||
|
||||
// Draw the string and fill to the end with spaces
|
||||
|
||||
TXT_DrawString(str);
|
||||
|
||||
for (i = TXT_UTF8_Strlen(str); i < list->widget.w; ++i)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_DropdownListDestructor(TXT_UNCAST_ARG(list))
|
||||
{
|
||||
}
|
||||
|
||||
static int TXT_DropdownListKeyPress(TXT_UNCAST_ARG(list), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_dropdown_list_t, list);
|
||||
|
||||
if (key == KEY_ENTER)
|
||||
{
|
||||
OpenSelectorWindow(list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TXT_DropdownListMousePress(TXT_UNCAST_ARG(list),
|
||||
int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_dropdown_list_t, list);
|
||||
|
||||
// Left mouse click does the same as selecting and pressing enter
|
||||
|
||||
if (b == TXT_MOUSE_LEFT)
|
||||
{
|
||||
TXT_DropdownListKeyPress(list, KEY_ENTER);
|
||||
}
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_dropdown_list_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_DropdownListSizeCalc,
|
||||
TXT_DropdownListDrawer,
|
||||
TXT_DropdownListKeyPress,
|
||||
TXT_DropdownListDestructor,
|
||||
TXT_DropdownListMousePress,
|
||||
NULL,
|
||||
};
|
||||
|
||||
txt_dropdown_list_t *TXT_NewDropdownList(int *variable, const char **values,
|
||||
int num_values)
|
||||
{
|
||||
txt_dropdown_list_t *list;
|
||||
|
||||
list = malloc(sizeof(txt_dropdown_list_t));
|
||||
|
||||
TXT_InitWidget(list, &txt_dropdown_list_class);
|
||||
list->variable = variable;
|
||||
list->values = values;
|
||||
list->num_values = num_values;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_DROPDOWN_H
|
||||
#define TXT_DROPDOWN_H
|
||||
|
||||
/**
|
||||
* @file txt_dropdown.h
|
||||
*
|
||||
* Dropdown list widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Dropdown list widget.
|
||||
*
|
||||
* A dropdown list allows the user to select from a list of values,
|
||||
* which appears when the list is selected.
|
||||
*
|
||||
* When the value of a dropdown list is changed, the "changed" signal
|
||||
* is emitted.
|
||||
*/
|
||||
|
||||
typedef struct txt_dropdown_list_s txt_dropdown_list_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
//
|
||||
// Drop-down list box.
|
||||
//
|
||||
|
||||
struct txt_dropdown_list_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
int *variable;
|
||||
const char **values;
|
||||
int num_values;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new dropdown list widget.
|
||||
*
|
||||
* The parameters specify a list of string labels, and a pointer to an
|
||||
* integer variable. The variable contains the current "value" of the
|
||||
* list, as an index within the list of labels.
|
||||
*
|
||||
* @param variable Pointer to the variable containing the
|
||||
* list's value.
|
||||
* @param values Pointer to an array of strings containing
|
||||
* the labels to use for the list (UTF-8 format).
|
||||
* @param num_values The number of variables in the list.
|
||||
*/
|
||||
|
||||
txt_dropdown_list_t *TXT_NewDropdownList(int *variable,
|
||||
const char **values, int num_values);
|
||||
|
||||
#endif /* #ifndef TXT_DROPDOWN_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,840 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Routines for selecting files.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_fileselect.h"
|
||||
#include "txt_inputbox.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_widget.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
struct txt_fileselect_s {
|
||||
txt_widget_t widget;
|
||||
txt_inputbox_t *inputbox;
|
||||
int size;
|
||||
const char *prompt;
|
||||
const char **extensions;
|
||||
};
|
||||
|
||||
// Dummy value to select a directory.
|
||||
|
||||
const char *TXT_DIRECTORY[] = { "__directory__", NULL };
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static char *ExecReadOutput(char **argv)
|
||||
{
|
||||
char *result;
|
||||
int completed;
|
||||
int pid, status, result_len;
|
||||
int pipefd[2];
|
||||
|
||||
if (pipe(pipefd) != 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
dup2(pipefd[1], fileno(stdout));
|
||||
execv(argv[0], argv);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
|
||||
|
||||
// Read program output into 'result' string.
|
||||
// Wait until the program has completed and (if it was successful)
|
||||
// a full line has been read.
|
||||
|
||||
result = NULL;
|
||||
result_len = 0;
|
||||
completed = 0;
|
||||
|
||||
while (!completed
|
||||
|| (status == 0 && (result == NULL || strchr(result, '\n') == NULL)))
|
||||
{
|
||||
char buf[64];
|
||||
int bytes;
|
||||
|
||||
if (!completed && waitpid(pid, &status, WNOHANG) != 0)
|
||||
{
|
||||
completed = 1;
|
||||
}
|
||||
|
||||
bytes = read(pipefd[0], buf, sizeof(buf));
|
||||
|
||||
if (bytes < 0)
|
||||
{
|
||||
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
{
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *new_result = realloc(result, result_len + bytes + 1);
|
||||
if (new_result == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
result = new_result;
|
||||
memcpy(result + result_len, buf, bytes);
|
||||
result_len += bytes;
|
||||
result[result_len] = '\0';
|
||||
}
|
||||
|
||||
usleep(100 * 1000);
|
||||
TXT_Sleep(1);
|
||||
TXT_UpdateScreen();
|
||||
}
|
||||
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
|
||||
// Must have a success exit code.
|
||||
|
||||
if (WEXITSTATUS(status) != 0)
|
||||
{
|
||||
free(result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
// Strip off newline from the end.
|
||||
|
||||
if (result != NULL && result[result_len - 1] == '\n')
|
||||
{
|
||||
result[result_len - 1] = '\0';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// This is currently disabled on Windows because it doesn't work.
|
||||
// Current issues:
|
||||
// * On Windows Vista+ the mouse cursor freezes when the dialog is
|
||||
// opened. This is probably some conflict with SDL (might be
|
||||
// resolved by opening the dialog in a separate thread so that
|
||||
// TXT_UpdateScreen can be run in the background).
|
||||
// * On Windows XP the program exits/crashes when the dialog is
|
||||
// closed.
|
||||
#if defined(_WIN32)
|
||||
|
||||
int TXT_CanSelectFiles(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *TXT_SelectFile(const char *window_title, const char **extensions)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#elif defined(xxxdisabled_WIN32)
|
||||
|
||||
// Windows code. Use comdlg32 to pop up a dialog box.
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
static BOOL (*MyGetOpenFileName)(LPOPENFILENAME) = NULL;
|
||||
static LPITEMIDLIST (*MySHBrowseForFolder)(LPBROWSEINFO) = NULL;
|
||||
static BOOL (*MySHGetPathFromIDList)(LPITEMIDLIST, LPTSTR) = NULL;
|
||||
|
||||
// Load library functions from DLL files.
|
||||
|
||||
static int LoadDLLs(void)
|
||||
{
|
||||
HMODULE comdlg32, shell32
|
||||
|
||||
comdlg32 = LoadLibraryW(L"comdlg32.dll");
|
||||
if (comdlg32 == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
shell32 = LoadLibraryW(L"shell32.dll");
|
||||
if (shell32 == NULL)
|
||||
{
|
||||
FreeLibrary(comdlg32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MyGetOpenFileName =
|
||||
(void *) GetProcAddress(comdlg32, "GetOpenFileNameA");
|
||||
MySHBrowseForFolder =
|
||||
(void *) GetProcAddress(shell32, "SHBrowseForFolder");
|
||||
MySHGetPathFromIDList =
|
||||
(void *) GetProcAddress(shell32, "SHGetPathFromIDList");
|
||||
|
||||
return MyGetOpenFileName != NULL
|
||||
&& MySHBrowseForFolder != NULL
|
||||
&& MySHGetPathFromIDList != NULL;
|
||||
}
|
||||
|
||||
static int InitLibraries(void)
|
||||
{
|
||||
static int initted = 0, success = 0;
|
||||
|
||||
if (!initted)
|
||||
{
|
||||
success = LoadDLLs();
|
||||
initted = 1;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Generate the "filter" string from the list of extensions.
|
||||
|
||||
static char *GenerateFilterString(const char **extensions)
|
||||
{
|
||||
unsigned int result_len = 1;
|
||||
unsigned int i;
|
||||
char *result, *out;
|
||||
size_t out_len, offset;
|
||||
|
||||
if (extensions == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
result_len += 16 + strlen(extensions[i]) * 3;
|
||||
}
|
||||
|
||||
result = malloc(result_len);
|
||||
out = result; out_len = result_len;
|
||||
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
// .wad files (*.wad)\0
|
||||
offset = TXT_snprintf(out, out_len, "%s files (*.%s)",
|
||||
extensions[i], extensions[i]);
|
||||
out += offset + 1; out_len -= offset + 1;
|
||||
|
||||
// *.wad\0
|
||||
offset = TXT_snprintf(out, out_len, "*.%s", extensions[i]);
|
||||
out_len += offset + 1; out_len -= offset + 1;
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int TXT_CanSelectFiles(void)
|
||||
{
|
||||
return InitLibraries();
|
||||
}
|
||||
|
||||
static char *SelectDirectory(char *window_title)
|
||||
{
|
||||
LPITEMIDLIST pidl;
|
||||
BROWSEINFO bi;
|
||||
char selected[MAX_PATH] = "";
|
||||
char *result;
|
||||
|
||||
ZeroMemory(&bi, sizeof(bi));
|
||||
bi.hwndOwner = NULL;
|
||||
bi.lpszTitle = window_title;
|
||||
bi.pszDisplayName = selected;
|
||||
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
|
||||
|
||||
pidl = MySHBrowseForFolder(&bi);
|
||||
|
||||
result = NULL;
|
||||
|
||||
if (pidl != NULL)
|
||||
{
|
||||
if (MySHGetPathFromIDList(pidl, selected))
|
||||
{
|
||||
result = strdup(selected);
|
||||
}
|
||||
|
||||
// TODO: Free pidl
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *TXT_SelectFile(const char *window_title, const char **extensions)
|
||||
{
|
||||
OPENFILENAME fm;
|
||||
char selected[MAX_PATH] = "";
|
||||
char *filter_string, *result;
|
||||
|
||||
if (!InitLibraries())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (extensions == TXT_DIRECTORY)
|
||||
{
|
||||
return SelectDirectory(window_title);
|
||||
}
|
||||
|
||||
filter_string = GenerateFilterString(extensions);
|
||||
|
||||
ZeroMemory(&fm, sizeof(fm));
|
||||
fm.lStructSize = sizeof(OPENFILENAME);
|
||||
fm.hwndOwner = NULL;
|
||||
fm.lpstrTitle = window_title;
|
||||
fm.lpstrFilter = filter_string;
|
||||
fm.lpstrFile = selected;
|
||||
fm.nMaxFile = MAX_PATH;
|
||||
fm.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
fm.lpstrDefExt = "";
|
||||
|
||||
if (!MyGetOpenFileName(&fm))
|
||||
{
|
||||
result = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = strdup(selected);
|
||||
}
|
||||
|
||||
free(filter_string);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#elif defined(__MACOSX__)
|
||||
|
||||
// Mac OS X code. Popping up a dialog requires Objective C/Cocoa
|
||||
// but we can get away with using AppleScript which avoids adding
|
||||
// an Objective C dependency. This is rather silly.
|
||||
|
||||
// Printf format string for the "wrapper" portion of the AppleScript:
|
||||
#define APPLESCRIPT_WRAPPER "copy POSIX path of (%s) to stdout"
|
||||
|
||||
static char *CreateEscapedString(const char *original)
|
||||
{
|
||||
char *result;
|
||||
const char *in;
|
||||
char *out;
|
||||
|
||||
// We need to take care not to overflow the buffer, so count exactly.
|
||||
#define ESCAPED_CHARS "\"\\"
|
||||
size_t count_extras = 2; // start counting the two quotes
|
||||
for (in = original; *in; ++in)
|
||||
{
|
||||
if (strchr(ESCAPED_CHARS, *in))
|
||||
{
|
||||
++count_extras;
|
||||
}
|
||||
}
|
||||
|
||||
result = malloc(strlen(original) + count_extras + 1);
|
||||
if (!result)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
out = result;
|
||||
*out++ = '"';
|
||||
for (in = original; *in; ++in)
|
||||
{
|
||||
if (strchr(ESCAPED_CHARS, *in))
|
||||
{
|
||||
*out++ = '\\';
|
||||
}
|
||||
*out++ = *in;
|
||||
}
|
||||
*out++ = '"';
|
||||
*out = 0;
|
||||
|
||||
return result;
|
||||
#undef ESCAPED_CHARS
|
||||
}
|
||||
|
||||
// Build list of extensions, like: {"wad","lmp","txt"}
|
||||
|
||||
static char *CreateExtensionsList(const char **extensions)
|
||||
{
|
||||
char *result, *escaped;
|
||||
unsigned int result_len;
|
||||
unsigned int i;
|
||||
|
||||
if (extensions == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result_len = 3;
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
result_len += 5 + strlen(extensions[i]) * 2;
|
||||
}
|
||||
|
||||
result = malloc(result_len);
|
||||
if (!result)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
TXT_StringCopy(result, "{", result_len);
|
||||
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
escaped = CreateEscapedString(extensions[i]);
|
||||
if (!escaped)
|
||||
{
|
||||
free(result);
|
||||
return NULL;
|
||||
}
|
||||
TXT_StringConcat(result, escaped, result_len);
|
||||
free(escaped);
|
||||
|
||||
if (extensions[i + 1] != NULL)
|
||||
{
|
||||
TXT_StringConcat(result, ",", result_len);
|
||||
}
|
||||
}
|
||||
|
||||
TXT_StringConcat(result, "}", result_len);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *GenerateSelector(const char *const window_title, const char **extensions)
|
||||
{
|
||||
const char *chooser;
|
||||
char *ext_list = NULL;
|
||||
char *window_title_escaped = NULL;
|
||||
char *result = NULL;
|
||||
unsigned int result_len = 64;
|
||||
|
||||
if (extensions == TXT_DIRECTORY)
|
||||
{
|
||||
chooser = "choose folder";
|
||||
}
|
||||
else
|
||||
{
|
||||
chooser = "choose file";
|
||||
ext_list = CreateExtensionsList(extensions);
|
||||
if (!ext_list)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate size.
|
||||
|
||||
if (window_title != NULL)
|
||||
{
|
||||
window_title_escaped = CreateEscapedString(window_title);
|
||||
if (!window_title_escaped)
|
||||
{
|
||||
free(ext_list);
|
||||
return NULL;
|
||||
}
|
||||
result_len += strlen(window_title_escaped);
|
||||
}
|
||||
if (ext_list != NULL)
|
||||
{
|
||||
result_len += strlen(ext_list);
|
||||
}
|
||||
|
||||
result = malloc(result_len);
|
||||
if (!result)
|
||||
{
|
||||
free(window_title_escaped);
|
||||
free(ext_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TXT_StringCopy(result, chooser, result_len);
|
||||
|
||||
if (window_title_escaped != NULL)
|
||||
{
|
||||
TXT_StringConcat(result, " with prompt ", result_len);
|
||||
TXT_StringConcat(result, window_title_escaped, result_len);
|
||||
}
|
||||
|
||||
if (ext_list != NULL)
|
||||
{
|
||||
TXT_StringConcat(result, " of type ", result_len);
|
||||
TXT_StringConcat(result, ext_list, result_len);
|
||||
}
|
||||
|
||||
free(window_title_escaped);
|
||||
free(ext_list);
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *GenerateAppleScript(const char *window_title, const char **extensions)
|
||||
{
|
||||
char *selector, *result;
|
||||
size_t result_len;
|
||||
|
||||
selector = GenerateSelector(window_title, extensions);
|
||||
if (!selector)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result_len = strlen(APPLESCRIPT_WRAPPER) + strlen(selector);
|
||||
result = malloc(result_len);
|
||||
if (!result)
|
||||
{
|
||||
free(selector);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TXT_snprintf(result, result_len, APPLESCRIPT_WRAPPER, selector);
|
||||
free(selector);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int TXT_CanSelectFiles(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *TXT_SelectFile(const char *window_title, const char **extensions)
|
||||
{
|
||||
char *argv[4];
|
||||
char *result, *applescript;
|
||||
|
||||
applescript = GenerateAppleScript(window_title, extensions);
|
||||
if (!applescript)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
argv[0] = "/usr/bin/osascript";
|
||||
argv[1] = "-e";
|
||||
argv[2] = applescript;
|
||||
argv[3] = NULL;
|
||||
|
||||
result = ExecReadOutput(argv);
|
||||
|
||||
free(applescript);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Linux version: invoke the Zenity command line program to pop up a
|
||||
// dialog box. This avoids adding Gtk+ as a compile dependency.
|
||||
|
||||
#define ZENITY_BINARY "/usr/bin/zenity"
|
||||
|
||||
static unsigned int NumExtensions(const char **extensions)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
|
||||
if (extensions != NULL)
|
||||
{
|
||||
for (result = 0; extensions[result] != NULL; ++result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ZenityAvailable(void)
|
||||
{
|
||||
return system(ZENITY_BINARY " --help >/dev/null 2>&1") == 0;
|
||||
}
|
||||
|
||||
int TXT_CanSelectFiles(void)
|
||||
{
|
||||
return ZenityAvailable();
|
||||
}
|
||||
|
||||
//
|
||||
// ExpandExtension
|
||||
// given an extension (like wad)
|
||||
// return a pointer to a string that is a case-insensitive
|
||||
// pattern representation (like [Ww][Aa][Dd])
|
||||
//
|
||||
static char *ExpandExtension(const char *orig)
|
||||
{
|
||||
int oldlen, newlen, i;
|
||||
char *c, *newext = NULL;
|
||||
|
||||
oldlen = strlen(orig);
|
||||
newlen = oldlen * 4; // pathological case: 'w' => '[Ww]'
|
||||
newext = malloc(newlen+1);
|
||||
|
||||
if (newext == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c = newext;
|
||||
for (i = 0; i < oldlen; ++i)
|
||||
{
|
||||
if (isalpha(orig[i]))
|
||||
{
|
||||
*c++ = '[';
|
||||
*c++ = tolower(orig[i]);
|
||||
*c++ = toupper(orig[i]);
|
||||
*c++ = ']';
|
||||
}
|
||||
else
|
||||
{
|
||||
*c++ = orig[i];
|
||||
}
|
||||
}
|
||||
*c = '\0';
|
||||
return newext;
|
||||
}
|
||||
|
||||
char *TXT_SelectFile(const char *window_title, const char **extensions)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t len;
|
||||
char *result;
|
||||
char **argv;
|
||||
int argc;
|
||||
|
||||
if (!ZenityAvailable())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
argv = calloc(5 + NumExtensions(extensions), sizeof(char *));
|
||||
argv[0] = strdup(ZENITY_BINARY);
|
||||
argv[1] = strdup("--file-selection");
|
||||
argc = 2;
|
||||
|
||||
if (window_title != NULL)
|
||||
{
|
||||
len = 10 + strlen(window_title);
|
||||
argv[argc] = malloc(len);
|
||||
TXT_snprintf(argv[argc], len, "--title=%s", window_title);
|
||||
++argc;
|
||||
}
|
||||
|
||||
if (extensions == TXT_DIRECTORY)
|
||||
{
|
||||
argv[argc] = strdup("--directory");
|
||||
++argc;
|
||||
}
|
||||
else if (extensions != NULL)
|
||||
{
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
char * newext = ExpandExtension(extensions[i]);
|
||||
if (newext)
|
||||
{
|
||||
len = 30 + strlen(extensions[i]) + strlen(newext);
|
||||
argv[argc] = malloc(len);
|
||||
TXT_snprintf(argv[argc], len, "--file-filter=.%s | *.%s",
|
||||
extensions[i], newext);
|
||||
++argc;
|
||||
free(newext);
|
||||
}
|
||||
}
|
||||
|
||||
argv[argc] = strdup("--file-filter=*.* | *.*");
|
||||
++argc;
|
||||
}
|
||||
|
||||
argv[argc] = NULL;
|
||||
|
||||
result = ExecReadOutput(argv);
|
||||
|
||||
for (i = 0; i < argc; ++i)
|
||||
{
|
||||
free(argv[i]);
|
||||
}
|
||||
|
||||
free(argv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void TXT_FileSelectSizeCalc(TXT_UNCAST_ARG(fileselect))
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
// Calculate widget size, but override the width to always
|
||||
// be the configured size.
|
||||
|
||||
TXT_CalcWidgetSize(fileselect->inputbox);
|
||||
fileselect->widget.w = fileselect->size;
|
||||
fileselect->widget.h = fileselect->inputbox->widget.h;
|
||||
}
|
||||
|
||||
static void TXT_FileSelectDrawer(TXT_UNCAST_ARG(fileselect))
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
// Input box widget inherits all the properties of the
|
||||
// file selector.
|
||||
|
||||
fileselect->inputbox->widget.x = fileselect->widget.x + 2;
|
||||
fileselect->inputbox->widget.y = fileselect->widget.y;
|
||||
fileselect->inputbox->widget.w = fileselect->widget.w - 2;
|
||||
fileselect->inputbox->widget.h = fileselect->widget.h;
|
||||
|
||||
// Triple bar symbol gives a distinguishing look to the file selector.
|
||||
TXT_DrawCodePageString("\xf0 ");
|
||||
TXT_BGColor(TXT_COLOR_BLACK, 0);
|
||||
TXT_DrawWidget(fileselect->inputbox);
|
||||
}
|
||||
|
||||
static void TXT_FileSelectDestructor(TXT_UNCAST_ARG(fileselect))
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
TXT_DestroyWidget(fileselect->inputbox);
|
||||
}
|
||||
|
||||
static int DoSelectFile(txt_fileselect_t *fileselect)
|
||||
{
|
||||
char *path;
|
||||
char **var;
|
||||
|
||||
if (TXT_CanSelectFiles())
|
||||
{
|
||||
path = TXT_SelectFile(fileselect->prompt,
|
||||
fileselect->extensions);
|
||||
|
||||
// Update inputbox variable.
|
||||
// If cancel was pressed (ie. NULL was returned by TXT_SelectFile)
|
||||
// then reset to empty string, not NULL).
|
||||
|
||||
if (path == NULL)
|
||||
{
|
||||
path = strdup("");
|
||||
}
|
||||
|
||||
var = fileselect->inputbox->value;
|
||||
free(*var);
|
||||
*var = path;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int TXT_FileSelectKeyPress(TXT_UNCAST_ARG(fileselect), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
// When the enter key is pressed, pop up a file selection dialog,
|
||||
// if file selectors work. Allow holding down 'alt' to override
|
||||
// use of the native file selector, so the user can just type a path.
|
||||
|
||||
if (!fileselect->inputbox->editing
|
||||
&& !TXT_GetModifierState(TXT_MOD_ALT)
|
||||
&& key == KEY_ENTER)
|
||||
{
|
||||
if (DoSelectFile(fileselect))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return TXT_WidgetKeyPress(fileselect->inputbox, key);
|
||||
}
|
||||
|
||||
static void TXT_FileSelectMousePress(TXT_UNCAST_ARG(fileselect),
|
||||
int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
if (!fileselect->inputbox->editing
|
||||
&& !TXT_GetModifierState(TXT_MOD_ALT)
|
||||
&& b == TXT_MOUSE_LEFT)
|
||||
{
|
||||
if (DoSelectFile(fileselect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TXT_WidgetMousePress(fileselect->inputbox, x, y, b);
|
||||
}
|
||||
|
||||
static void TXT_FileSelectFocused(TXT_UNCAST_ARG(fileselect), int focused)
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
TXT_SetWidgetFocus(fileselect->inputbox, focused);
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_fileselect_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_FileSelectSizeCalc,
|
||||
TXT_FileSelectDrawer,
|
||||
TXT_FileSelectKeyPress,
|
||||
TXT_FileSelectDestructor,
|
||||
TXT_FileSelectMousePress,
|
||||
NULL,
|
||||
TXT_FileSelectFocused,
|
||||
};
|
||||
|
||||
// If the (inner) inputbox widget is changed, emit a change to the
|
||||
// outer (fileselect) widget.
|
||||
|
||||
static void InputBoxChanged(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(fileselect))
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
TXT_EmitSignal(&fileselect->widget, "changed");
|
||||
}
|
||||
|
||||
txt_fileselect_t *TXT_NewFileSelector(char **variable, int size,
|
||||
const char *prompt, const char **extensions)
|
||||
{
|
||||
txt_fileselect_t *fileselect;
|
||||
|
||||
fileselect = malloc(sizeof(txt_fileselect_t));
|
||||
TXT_InitWidget(fileselect, &txt_fileselect_class);
|
||||
fileselect->inputbox = TXT_NewInputBox(variable, 1024);
|
||||
fileselect->inputbox->widget.parent = &fileselect->widget;
|
||||
fileselect->size = size;
|
||||
fileselect->prompt = prompt;
|
||||
fileselect->extensions = extensions;
|
||||
|
||||
TXT_SignalConnect(fileselect->inputbox, "changed",
|
||||
InputBoxChanged, fileselect);
|
||||
|
||||
return fileselect;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Routines for selecting files, and the txt_fileselect_t widget.
|
||||
//
|
||||
|
||||
#ifndef TXT_FILESELECT_H
|
||||
#define TXT_FILESELECT_H
|
||||
|
||||
/**
|
||||
* @file txt_fileselect.h
|
||||
*
|
||||
* File selection widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* File selection widget.
|
||||
*
|
||||
* A file selection widget resembles an input box (@ref txt_inputbox_t)
|
||||
* but opens a file selector dialog box when clicked.
|
||||
*/
|
||||
|
||||
typedef struct txt_fileselect_s txt_fileselect_t;
|
||||
|
||||
/**
|
||||
* Returns non-zero if a native file selector is available on this
|
||||
* platform.
|
||||
*/
|
||||
|
||||
int TXT_CanSelectFiles(void);
|
||||
|
||||
/**
|
||||
* Open a native file selector to select a file.
|
||||
*
|
||||
* @param prompt Pointer to a string containing a prompt to display
|
||||
* in the window.
|
||||
* @param extensions NULL-terminated list of filename extensions for
|
||||
* files that can be selected, or @ref TXT_DIRECTORY
|
||||
* to select directories.
|
||||
*/
|
||||
|
||||
char *TXT_SelectFile(const char *prompt, const char **extensions);
|
||||
|
||||
/**
|
||||
* Create a new txt_fileselect_t widget.
|
||||
*
|
||||
* @param variable Pointer to a char * variable in which the selected
|
||||
* file should be stored (UTF-8 format).
|
||||
* @param size Width of the file selector widget in characters.
|
||||
* @param prompt Pointer to a string containing a prompt to display
|
||||
* in the file selection window.
|
||||
* @param extensions NULL-terminated list of filename extensions that
|
||||
* can be used for this widget, or @ref TXT_DIRECTORY
|
||||
* to select directories.
|
||||
*/
|
||||
|
||||
txt_fileselect_t *TXT_NewFileSelector(char **variable, int size,
|
||||
const char *prompt, const char **extensions);
|
||||
|
||||
/**
|
||||
* Special value to use for 'extensions' that selects a directory
|
||||
* instead of a file.
|
||||
*/
|
||||
|
||||
extern const char *TXT_DIRECTORY[];
|
||||
|
||||
#endif /* #ifndef TXT_FILESELECT_H */
|
||||
|
||||
@@ -0,0 +1,556 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
|
||||
typedef struct txt_cliparea_s txt_cliparea_t;
|
||||
|
||||
struct txt_cliparea_s
|
||||
{
|
||||
int x1, x2;
|
||||
int y1, y2;
|
||||
txt_cliparea_t *next;
|
||||
};
|
||||
|
||||
// Array of border characters for drawing windows. The array looks like this:
|
||||
//
|
||||
// +-++
|
||||
// | ||
|
||||
// +-++
|
||||
// +-++
|
||||
|
||||
static const int borders[4][4] =
|
||||
{
|
||||
{0xda, 0xc4, 0xc2, 0xbf},
|
||||
{0xb3, ' ', 0xb3, 0xb3},
|
||||
{0xc3, 0xc4, 0xc5, 0xb4},
|
||||
{0xc0, 0xc4, 0xc1, 0xd9},
|
||||
};
|
||||
|
||||
static txt_cliparea_t *cliparea = NULL;
|
||||
|
||||
#define VALID_X(x) ((x) >= cliparea->x1 && (x) < cliparea->x2)
|
||||
#define VALID_Y(y) ((y) >= cliparea->y1 && (y) < cliparea->y2)
|
||||
|
||||
void TXT_DrawDesktopBackground(const char *title)
|
||||
{
|
||||
int i;
|
||||
unsigned char *screendata;
|
||||
unsigned char *p;
|
||||
|
||||
screendata = TXT_GetScreenData();
|
||||
|
||||
// Fill the screen with gradient characters
|
||||
|
||||
p = screendata;
|
||||
|
||||
for (i=0; i<TXT_SCREEN_W * TXT_SCREEN_H; ++i)
|
||||
{
|
||||
*p++ = 0xb1;
|
||||
*p++ = TXT_COLOR_GREY | (TXT_COLOR_BLUE << 4);
|
||||
}
|
||||
|
||||
// Draw the top and bottom banners
|
||||
|
||||
p = screendata;
|
||||
|
||||
for (i = 0; i<TXT_SCREEN_W; ++i)
|
||||
{
|
||||
*p++ = ' ';
|
||||
*p++ = TXT_COLOR_BLACK | (TXT_COLOR_GREY << 4);
|
||||
}
|
||||
|
||||
p = screendata + (TXT_SCREEN_H - 1) * TXT_SCREEN_W * 2;
|
||||
|
||||
for (i = 0; i<TXT_SCREEN_W; ++i)
|
||||
{
|
||||
*p++ = ' ';
|
||||
*p++ = TXT_COLOR_BLACK | (TXT_COLOR_GREY << 4);
|
||||
}
|
||||
|
||||
// Print the title
|
||||
|
||||
TXT_GotoXY(0, 0);
|
||||
TXT_FGColor(TXT_COLOR_BLACK);
|
||||
TXT_BGColor(TXT_COLOR_GREY, 0);
|
||||
|
||||
TXT_DrawString(" ");
|
||||
TXT_DrawString(title);
|
||||
}
|
||||
|
||||
void TXT_DrawShadow(int x, int y, int w, int h)
|
||||
{
|
||||
unsigned char *screendata;
|
||||
unsigned char *p;
|
||||
int x1, y1;
|
||||
|
||||
screendata = TXT_GetScreenData();
|
||||
|
||||
for (y1=y; y1<y+h; ++y1)
|
||||
{
|
||||
p = screendata + (y1 * TXT_SCREEN_W + x) * 2;
|
||||
|
||||
for (x1=x; x1<x+w; ++x1)
|
||||
{
|
||||
if (VALID_X(x1) && VALID_Y(y1))
|
||||
{
|
||||
p[1] = TXT_COLOR_DARK_GREY;
|
||||
}
|
||||
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h, int titlecolor, int framecolor, int customwin)
|
||||
{
|
||||
txt_saved_colors_t colors;
|
||||
int x1, y1;
|
||||
int bx, by;
|
||||
|
||||
TXT_SaveColors(&colors);
|
||||
|
||||
if (customwin == 1)
|
||||
{
|
||||
TXT_FGColor(framecolor);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
}
|
||||
|
||||
for (y1=y; y1<y+h; ++y1)
|
||||
{
|
||||
// Select the appropriate row and column in the borders
|
||||
// array to pick the appropriate character to draw at
|
||||
// this location.
|
||||
//
|
||||
// Draw a horizontal line on the third line down, so we
|
||||
// draw a box around the title.
|
||||
|
||||
by = y1 == y ? 0 :
|
||||
y1 == y + 2 && title != NULL ? 2 :
|
||||
y1 == y + h - 1 ? 3 : 1;
|
||||
|
||||
for (x1=x; x1<x+w; ++x1)
|
||||
{
|
||||
bx = x1 == x ? 0 :
|
||||
x1 == x + w - 1 ? 3 : 1;
|
||||
|
||||
if (VALID_X(x1) && VALID_Y(y1))
|
||||
{
|
||||
TXT_GotoXY(x1, y1);
|
||||
TXT_PutChar(borders[by][bx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the title
|
||||
|
||||
if (title != NULL)
|
||||
{
|
||||
TXT_GotoXY(x + 1, y + 1);
|
||||
TXT_BGColor(TXT_COLOR_GREY, 0);
|
||||
|
||||
if (customwin == 1)
|
||||
{
|
||||
TXT_FGColor(titlecolor);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_FGColor(TXT_COLOR_BLUE);
|
||||
}
|
||||
|
||||
for (x1=0; x1<w-2; ++x1)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
|
||||
TXT_GotoXY(x + (w - TXT_UTF8_Strlen(title)) / 2, y + 1);
|
||||
TXT_DrawString(title);
|
||||
}
|
||||
|
||||
// Draw the window's shadow.
|
||||
|
||||
TXT_DrawShadow(x + 2, y + h, w, 1);
|
||||
TXT_DrawShadow(x + w, y + 1, 2, h);
|
||||
|
||||
TXT_RestoreColors(&colors);
|
||||
}
|
||||
|
||||
void TXT_DrawSpecialSeparator(int x, int y, int w, int h, int sepcolor, int customwin)
|
||||
{
|
||||
txt_saved_colors_t colors;
|
||||
|
||||
int y1;
|
||||
int by;
|
||||
int bx;
|
||||
|
||||
int x1;
|
||||
int b;
|
||||
|
||||
TXT_SaveColors(&colors);
|
||||
|
||||
if (customwin == 1)
|
||||
{
|
||||
TXT_FGColor(sepcolor);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
}
|
||||
|
||||
if (!VALID_Y(y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (y1 = y; y1 < y + h; ++y1)
|
||||
{
|
||||
// Select the appropriate row and column in the borders
|
||||
// array to pick the appropriate character to draw at
|
||||
// this location.
|
||||
|
||||
by = y1 == y ? 0 :
|
||||
y1 == y + h - 1 ? 3 : 1;
|
||||
|
||||
for (x1 = x; x1 < x + w; ++x1)
|
||||
{
|
||||
bx = x1 == x ? 0 :
|
||||
x1 == x + w - 1 ? 3 : 1;
|
||||
|
||||
if (VALID_X(x1) && VALID_Y(y1))
|
||||
{
|
||||
TXT_GotoXY(x1, y1);
|
||||
TXT_PutChar(borders[by][bx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TXT_RestoreColors(&colors);
|
||||
}
|
||||
|
||||
void TXT_DrawSeparator(int x, int y, int w, int sepcolor, int customwin)
|
||||
{
|
||||
txt_saved_colors_t colors;
|
||||
unsigned char *data;
|
||||
int x1;
|
||||
int b;
|
||||
|
||||
data = TXT_GetScreenData();
|
||||
|
||||
TXT_SaveColors(&colors);
|
||||
|
||||
if (customwin == 1)
|
||||
{
|
||||
TXT_FGColor(sepcolor);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
}
|
||||
|
||||
if (!VALID_Y(y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data += (y * TXT_SCREEN_W + x) * 2;
|
||||
|
||||
for (x1=x; x1<x+w; ++x1)
|
||||
{
|
||||
TXT_GotoXY(x1, y);
|
||||
|
||||
b = x1 == x ? 0 :
|
||||
x1 == x + w - 1 ? 3 :
|
||||
1;
|
||||
|
||||
if (VALID_X(x1))
|
||||
{
|
||||
// Read the current value from the screen
|
||||
// Check that it matches what the window should look like if
|
||||
// there is no separator, then apply the separator
|
||||
|
||||
if (*data == borders[1][b])
|
||||
{
|
||||
TXT_PutChar(borders[2][b]);
|
||||
}
|
||||
}
|
||||
|
||||
data += 2;
|
||||
}
|
||||
|
||||
TXT_RestoreColors(&colors);
|
||||
}
|
||||
|
||||
// Alternative to TXT_DrawString() where the argument is a "code page
|
||||
// string" - characters are in native code page format and not UTF-8.
|
||||
void TXT_DrawCodePageString(const char *s)
|
||||
{
|
||||
int x, y;
|
||||
int x1;
|
||||
const char *p;
|
||||
|
||||
TXT_GetXY(&x, &y);
|
||||
|
||||
if (VALID_Y(y))
|
||||
{
|
||||
x1 = x;
|
||||
|
||||
for (p = s; *p != '\0'; ++p)
|
||||
{
|
||||
if (VALID_X(x1))
|
||||
{
|
||||
TXT_GotoXY(x1, y);
|
||||
TXT_PutChar(*p);
|
||||
}
|
||||
|
||||
x1 += 1;
|
||||
}
|
||||
}
|
||||
|
||||
TXT_GotoXY(x + strlen(s), y);
|
||||
}
|
||||
|
||||
static void PutUnicodeChar(unsigned int c)
|
||||
{
|
||||
int d;
|
||||
|
||||
// Treat control characters specially.
|
||||
if (c == '\n' || c == '\b')
|
||||
{
|
||||
TXT_PutChar(c);
|
||||
return;
|
||||
}
|
||||
|
||||
// Map Unicode character into the symbol used to represent it in this
|
||||
// code page. For unrepresentable characters, print a fallback instead.
|
||||
// Note that we use TXT_PutSymbol() here because we just want to do a
|
||||
// raw write into the screen buffer.
|
||||
d = TXT_UnicodeCharacter(c);
|
||||
|
||||
if (d >= 0)
|
||||
{
|
||||
TXT_PutSymbol(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_PutSymbol('\xa8');
|
||||
}
|
||||
}
|
||||
|
||||
void TXT_DrawString(const char *s)
|
||||
{
|
||||
int x, y;
|
||||
int x1;
|
||||
const char *p;
|
||||
unsigned int c;
|
||||
|
||||
TXT_GetXY(&x, &y);
|
||||
|
||||
if (VALID_Y(y))
|
||||
{
|
||||
x1 = x;
|
||||
|
||||
for (p = s; *p != '\0'; )
|
||||
{
|
||||
c = TXT_DecodeUTF8(&p);
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (VALID_X(x1))
|
||||
{
|
||||
TXT_GotoXY(x1, y);
|
||||
PutUnicodeChar(c);
|
||||
}
|
||||
|
||||
x1 += 1;
|
||||
}
|
||||
}
|
||||
|
||||
TXT_GotoXY(x + TXT_UTF8_Strlen(s), y);
|
||||
}
|
||||
|
||||
void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range)
|
||||
{
|
||||
txt_saved_colors_t colors;
|
||||
int x1;
|
||||
int cursor_x;
|
||||
|
||||
if (!VALID_Y(y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TXT_SaveColors(&colors);
|
||||
TXT_FGColor(TXT_COLOR_BLACK);
|
||||
TXT_BGColor(TXT_COLOR_GREY, 0);
|
||||
|
||||
TXT_GotoXY(x, y);
|
||||
TXT_PutChar('\x1b');
|
||||
|
||||
cursor_x = x + 1;
|
||||
|
||||
if (range > 0)
|
||||
{
|
||||
cursor_x += (cursor * (w - 3)) / range;
|
||||
}
|
||||
|
||||
if (cursor_x > x + w - 2)
|
||||
{
|
||||
cursor_x = x + w - 2;
|
||||
}
|
||||
|
||||
for (x1=x+1; x1<x+w-1; ++x1)
|
||||
{
|
||||
if (VALID_X(x1))
|
||||
{
|
||||
if (x1 == cursor_x)
|
||||
{
|
||||
TXT_PutChar('\xdb');
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_PutChar('\xb1');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TXT_PutChar('\x1a');
|
||||
TXT_RestoreColors(&colors);
|
||||
}
|
||||
|
||||
void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range)
|
||||
{
|
||||
txt_saved_colors_t colors;
|
||||
int y1;
|
||||
int cursor_y;
|
||||
|
||||
if (!VALID_X(x))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TXT_SaveColors(&colors);
|
||||
TXT_FGColor(TXT_COLOR_BLACK);
|
||||
TXT_BGColor(TXT_COLOR_GREY, 0);
|
||||
|
||||
TXT_GotoXY(x, y);
|
||||
TXT_PutChar('\x18');
|
||||
|
||||
cursor_y = y + 1;
|
||||
|
||||
if (cursor_y > y + h - 2)
|
||||
{
|
||||
cursor_y = y + h - 2;
|
||||
}
|
||||
|
||||
if (range > 0)
|
||||
{
|
||||
cursor_y += (cursor * (h - 3)) / range;
|
||||
}
|
||||
|
||||
for (y1=y+1; y1<y+h-1; ++y1)
|
||||
{
|
||||
if (VALID_Y(y1))
|
||||
{
|
||||
TXT_GotoXY(x, y1);
|
||||
|
||||
if (y1 == cursor_y)
|
||||
{
|
||||
TXT_PutChar('\xdb');
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_PutChar('\xb1');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TXT_GotoXY(x, y + h - 1);
|
||||
TXT_PutChar('\x19');
|
||||
TXT_RestoreColors(&colors);
|
||||
}
|
||||
|
||||
void TXT_InitClipArea(void)
|
||||
{
|
||||
if (cliparea == NULL)
|
||||
{
|
||||
cliparea = malloc(sizeof(txt_cliparea_t));
|
||||
cliparea->x1 = 0;
|
||||
cliparea->x2 = TXT_SCREEN_W;
|
||||
cliparea->y1 = 0;
|
||||
cliparea->y2 = TXT_SCREEN_H;
|
||||
cliparea->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void TXT_PushClipArea(int x1, int x2, int y1, int y2)
|
||||
{
|
||||
txt_cliparea_t *newarea;
|
||||
|
||||
newarea = malloc(sizeof(txt_cliparea_t));
|
||||
|
||||
// Set the new clip area to the intersection of the old
|
||||
// area and the new one.
|
||||
|
||||
newarea->x1 = cliparea->x1;
|
||||
newarea->x2 = cliparea->x2;
|
||||
newarea->y1 = cliparea->y1;
|
||||
newarea->y2 = cliparea->y2;
|
||||
|
||||
if (x1 > newarea->x1)
|
||||
newarea->x1 = x1;
|
||||
if (x2 < newarea->x2)
|
||||
newarea->x2 = x2;
|
||||
if (y1 > newarea->y1)
|
||||
newarea->y1 = y1;
|
||||
if (y2 < newarea->y2)
|
||||
newarea->y2 = y2;
|
||||
|
||||
#if 0
|
||||
printf("New scrollable area: %i,%i-%i,%i\n", x1, y1, x2, y2);
|
||||
#endif
|
||||
|
||||
// Hook into the list
|
||||
|
||||
newarea->next = cliparea;
|
||||
cliparea = newarea;
|
||||
}
|
||||
|
||||
void TXT_PopClipArea(void)
|
||||
{
|
||||
txt_cliparea_t *next_cliparea;
|
||||
|
||||
// Never pop the last entry
|
||||
|
||||
if (cliparea->next == NULL)
|
||||
return;
|
||||
|
||||
// Unlink the last entry and delete
|
||||
|
||||
next_cliparea = cliparea->next;
|
||||
free(cliparea);
|
||||
cliparea = next_cliparea;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Text mode emulation in SDL
|
||||
//
|
||||
|
||||
#ifndef TXT_GUI_H
|
||||
#define TXT_GUI_H
|
||||
|
||||
#define TXT_INACTIVE_WINDOW_BACKGROUND TXT_COLOR_BLACK
|
||||
#define TXT_ACTIVE_WINDOW_BACKGROUND TXT_COLOR_BLUE
|
||||
#define TXT_HOVER_BACKGROUND TXT_COLOR_CYAN
|
||||
|
||||
void TXT_DrawDesktopBackground(const char *title);
|
||||
void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h, int titlecolor, int framecolor, int customwin);
|
||||
void TXT_DrawSeparator(int x, int y, int w, int sepcolor, int customwin);
|
||||
void TXT_DrawSpecialSeparator(int x, int y, int w, int h, int sepcolor, int customwin);
|
||||
void TXT_DrawCodePageString(const char *s);
|
||||
void TXT_DrawString(const char *s);
|
||||
int TXT_CanDrawCharacter(unsigned int c);
|
||||
|
||||
void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range);
|
||||
void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range);
|
||||
|
||||
void TXT_InitClipArea(void);
|
||||
void TXT_PushClipArea(int x1, int x2, int y1, int y2);
|
||||
void TXT_PopClipArea(void);
|
||||
|
||||
#endif /* #ifndef TXT_GUI_H */
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_inputbox.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
extern txt_widget_class_t txt_inputbox_class;
|
||||
extern txt_widget_class_t txt_int_inputbox_class;
|
||||
|
||||
static void SetBufferFromValue(txt_inputbox_t *inputbox)
|
||||
{
|
||||
if (inputbox->widget.widget_class == &txt_inputbox_class)
|
||||
{
|
||||
char **value = (char **) inputbox->value;
|
||||
|
||||
if (*value != NULL)
|
||||
{
|
||||
TXT_StringCopy(inputbox->buffer, *value, strnlen(*value, inputbox->buffer_len) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_StringCopy(inputbox->buffer, "", inputbox->buffer_len);
|
||||
}
|
||||
}
|
||||
else if (inputbox->widget.widget_class == &txt_int_inputbox_class)
|
||||
{
|
||||
int *value = (int *) inputbox->value;
|
||||
TXT_snprintf(inputbox->buffer, inputbox->buffer_len, "%i", *value);
|
||||
}
|
||||
}
|
||||
|
||||
static void StartEditing(txt_inputbox_t *inputbox)
|
||||
{
|
||||
// Integer input boxes start from an empty buffer:
|
||||
|
||||
if (inputbox->widget.widget_class == &txt_int_inputbox_class)
|
||||
{
|
||||
TXT_StringCopy(inputbox->buffer, "", inputbox->buffer_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetBufferFromValue(inputbox);
|
||||
}
|
||||
|
||||
// Switch to text input mode so we get shifted input.
|
||||
TXT_SetInputMode(TXT_INPUT_TEXT);
|
||||
inputbox->editing = 1;
|
||||
}
|
||||
|
||||
static void StopEditing(txt_inputbox_t *inputbox)
|
||||
{
|
||||
if (inputbox->editing)
|
||||
{
|
||||
// Switch back to normal input mode.
|
||||
TXT_SetInputMode(TXT_INPUT_NORMAL);
|
||||
inputbox->editing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void FinishEditing(txt_inputbox_t *inputbox)
|
||||
{
|
||||
if (!inputbox->editing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the new value back to the variable.
|
||||
|
||||
if (inputbox->widget.widget_class == &txt_inputbox_class)
|
||||
{
|
||||
free(*((char **)inputbox->value));
|
||||
*((char **) inputbox->value) = strdup(inputbox->buffer);
|
||||
}
|
||||
else if (inputbox->widget.widget_class == &txt_int_inputbox_class)
|
||||
{
|
||||
*((int *) inputbox->value) = atoi(inputbox->buffer);
|
||||
}
|
||||
|
||||
TXT_EmitSignal(&inputbox->widget, "changed");
|
||||
|
||||
StopEditing(inputbox);
|
||||
}
|
||||
|
||||
static void TXT_InputBoxSizeCalc(TXT_UNCAST_ARG(inputbox))
|
||||
{
|
||||
TXT_CAST_ARG(txt_inputbox_t, inputbox);
|
||||
|
||||
// Enough space for the box + cursor
|
||||
|
||||
if(inputbox->drawsize)
|
||||
inputbox->widget.w = inputbox->drawsize + 1;
|
||||
else
|
||||
inputbox->widget.w = inputbox->size + 1;
|
||||
|
||||
inputbox->widget.h = 1;
|
||||
}
|
||||
|
||||
static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox))
|
||||
{
|
||||
TXT_CAST_ARG(txt_inputbox_t, inputbox);
|
||||
int focused;
|
||||
int i;
|
||||
int chars;
|
||||
int w;
|
||||
|
||||
focused = inputbox->widget.focused;
|
||||
w = inputbox->widget.w;
|
||||
|
||||
// Select the background color based on whether we are currently
|
||||
// editing, and if not, whether the widget is focused.
|
||||
|
||||
if (inputbox->editing && focused)
|
||||
{
|
||||
TXT_BGColor(TXT_COLOR_BLACK, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_SetWidgetBG(inputbox);
|
||||
}
|
||||
|
||||
if (!inputbox->editing)
|
||||
{
|
||||
// If not editing, use the current value from inputbox->value.
|
||||
|
||||
SetBufferFromValue(inputbox);
|
||||
}
|
||||
|
||||
// If string size exceeds the widget's width, show only the end.
|
||||
|
||||
if (TXT_UTF8_Strlen(inputbox->buffer) > w - 1)
|
||||
{
|
||||
TXT_DrawCodePageString("\xae");
|
||||
TXT_DrawString(
|
||||
TXT_UTF8_SkipChars(inputbox->buffer,
|
||||
TXT_UTF8_Strlen(inputbox->buffer) - w + 2));
|
||||
chars = w - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_DrawString(inputbox->buffer);
|
||||
chars = TXT_UTF8_Strlen(inputbox->buffer);
|
||||
}
|
||||
|
||||
if (chars < w && inputbox->editing && focused)
|
||||
{
|
||||
TXT_BGColor(TXT_COLOR_BLACK, 1);
|
||||
TXT_DrawString("_");
|
||||
++chars;
|
||||
}
|
||||
|
||||
for (i=chars; i < w; ++i)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_InputBoxDestructor(TXT_UNCAST_ARG(inputbox))
|
||||
{
|
||||
TXT_CAST_ARG(txt_inputbox_t, inputbox);
|
||||
|
||||
StopEditing(inputbox);
|
||||
free(inputbox->buffer);
|
||||
}
|
||||
|
||||
static void Backspace(txt_inputbox_t *inputbox)
|
||||
{
|
||||
unsigned int len;
|
||||
char *p;
|
||||
|
||||
len = TXT_UTF8_Strlen(inputbox->buffer);
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
p = TXT_UTF8_SkipChars(inputbox->buffer, len - 1);
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static void AddCharacter(txt_inputbox_t *inputbox, int key)
|
||||
{
|
||||
char *end, *p;
|
||||
|
||||
if (TXT_UTF8_Strlen(inputbox->buffer) < inputbox->size)
|
||||
{
|
||||
// Add character to the buffer
|
||||
|
||||
end = inputbox->buffer + strlen(inputbox->buffer);
|
||||
p = TXT_EncodeUTF8(end, key);
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static int TXT_InputBoxKeyPress(TXT_UNCAST_ARG(inputbox), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_inputbox_t, inputbox);
|
||||
unsigned int c;
|
||||
|
||||
if (!inputbox->editing)
|
||||
{
|
||||
if (key == KEY_ENTER)
|
||||
{
|
||||
StartEditing(inputbox);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Backspace or delete erases the contents of the box.
|
||||
|
||||
if ((key == KEY_DEL || key == KEY_BACKSPACE)
|
||||
&& inputbox->widget.widget_class == &txt_inputbox_class)
|
||||
{
|
||||
free(*((char **)inputbox->value));
|
||||
*((char **) inputbox->value) = strdup("");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (key == KEY_ENTER)
|
||||
{
|
||||
FinishEditing(inputbox);
|
||||
}
|
||||
|
||||
if (key == KEY_ESCAPE)
|
||||
{
|
||||
StopEditing(inputbox);
|
||||
}
|
||||
|
||||
if (key == KEY_BACKSPACE)
|
||||
{
|
||||
Backspace(inputbox);
|
||||
}
|
||||
|
||||
c = TXT_KEY_TO_UNICODE(key);
|
||||
|
||||
// Add character to the buffer, but only if it's a printable character
|
||||
// that we can represent on the screen.
|
||||
if (isprint(c)
|
||||
|| (c >= 128 && TXT_UnicodeCharacter(c) >= 0))
|
||||
{
|
||||
AddCharacter(inputbox, c);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void TXT_InputBoxMousePress(TXT_UNCAST_ARG(inputbox),
|
||||
int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_inputbox_t, inputbox);
|
||||
|
||||
if (b == TXT_MOUSE_LEFT)
|
||||
{
|
||||
// Make mouse clicks start editing the box
|
||||
|
||||
if (!inputbox->editing)
|
||||
{
|
||||
// Send a simulated keypress to start editing
|
||||
|
||||
TXT_WidgetKeyPress(inputbox, KEY_ENTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_InputBoxFocused(TXT_UNCAST_ARG(inputbox), int focused)
|
||||
{
|
||||
TXT_CAST_ARG(txt_inputbox_t, inputbox);
|
||||
|
||||
// Stop editing when we lose focus.
|
||||
|
||||
if (inputbox->editing && !focused)
|
||||
{
|
||||
FinishEditing(inputbox);
|
||||
}
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_inputbox_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_InputBoxSizeCalc,
|
||||
TXT_InputBoxDrawer,
|
||||
TXT_InputBoxKeyPress,
|
||||
TXT_InputBoxDestructor,
|
||||
TXT_InputBoxMousePress,
|
||||
NULL,
|
||||
TXT_InputBoxFocused,
|
||||
};
|
||||
|
||||
txt_widget_class_t txt_int_inputbox_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_InputBoxSizeCalc,
|
||||
TXT_InputBoxDrawer,
|
||||
TXT_InputBoxKeyPress,
|
||||
TXT_InputBoxDestructor,
|
||||
TXT_InputBoxMousePress,
|
||||
NULL,
|
||||
TXT_InputBoxFocused,
|
||||
};
|
||||
|
||||
static txt_inputbox_t *NewInputBox(txt_widget_class_t *widget_class,
|
||||
void *value, int size)
|
||||
{
|
||||
txt_inputbox_t *inputbox;
|
||||
|
||||
inputbox = malloc(sizeof(txt_inputbox_t));
|
||||
|
||||
TXT_InitWidget(inputbox, widget_class);
|
||||
inputbox->value = value;
|
||||
inputbox->size = size;
|
||||
// 'size' is the maximum number of characters that can be entered,
|
||||
// but for a UTF-8 string, each character can take up to four
|
||||
// characters.
|
||||
inputbox->buffer_len = size * 4 + 1;
|
||||
inputbox->drawsize = 0;
|
||||
inputbox->buffer = malloc(inputbox->buffer_len);
|
||||
inputbox->editing = 0;
|
||||
|
||||
return inputbox;
|
||||
}
|
||||
|
||||
static txt_inputbox_t* NewInputBoxCustomSize(txt_widget_class_t* widget_class,
|
||||
void* value, int size, int drawsize)
|
||||
{
|
||||
txt_inputbox_t* inputbox;
|
||||
|
||||
inputbox = malloc(sizeof(txt_inputbox_t));
|
||||
|
||||
TXT_InitWidget(inputbox, widget_class);
|
||||
inputbox->value = value;
|
||||
inputbox->size = size;
|
||||
// 'size' is the maximum number of characters that can be entered,
|
||||
// but for a UTF-8 string, each character can take up to four
|
||||
// characters.
|
||||
inputbox->buffer_len = size * 4 + 1;
|
||||
inputbox->drawsize = drawsize;
|
||||
inputbox->buffer = malloc(inputbox->buffer_len);
|
||||
inputbox->editing = 0;
|
||||
|
||||
return inputbox;
|
||||
}
|
||||
|
||||
txt_inputbox_t *TXT_NewInputBox(char **value, int size)
|
||||
{
|
||||
return NewInputBox(&txt_inputbox_class, value, size);
|
||||
}
|
||||
|
||||
txt_inputbox_t *TXT_NewIntInputBox(int *value, int size)
|
||||
{
|
||||
return NewInputBox(&txt_int_inputbox_class, value, size);
|
||||
}
|
||||
|
||||
txt_inputbox_t* TXT_NewInputBoxCustomSize(char** value, int size, int drawsize)
|
||||
{
|
||||
return NewInputBoxCustomSize(&txt_inputbox_class, value, size, drawsize);
|
||||
}
|
||||
|
||||
txt_inputbox_t* TXT_NewIntInputBoxCustomSize(int* value, int size, int drawsize)
|
||||
{
|
||||
return NewInputBoxCustomSize(&txt_int_inputbox_class, value, size, drawsize);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_INPUTBOX_H
|
||||
#define TXT_INPUTBOX_H
|
||||
|
||||
/**
|
||||
* @file txt_inputbox.h
|
||||
*
|
||||
* Input box widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Input box widget.
|
||||
*
|
||||
* An input box is a widget that displays a value, which can be
|
||||
* selected to enter a new value.
|
||||
*
|
||||
* Input box widgets can be of an integer or string type.
|
||||
*/
|
||||
|
||||
typedef struct txt_inputbox_s txt_inputbox_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_inputbox_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
char *buffer;
|
||||
size_t buffer_len;
|
||||
unsigned int size;
|
||||
unsigned int drawsize;
|
||||
int editing;
|
||||
void *value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new input box widget for controlling a string value.
|
||||
*
|
||||
* @param value Pointer to a string variable that contains
|
||||
* a pointer to the current value of the
|
||||
* input box. The value should be allocated
|
||||
* dynamically; when the string is changed it
|
||||
* will be freed and the variable set to point
|
||||
* to the new string value. String will be in
|
||||
* UTF-8 format.
|
||||
* @param size Width of the input box, in characters.
|
||||
* @return Pointer to the new input box widget.
|
||||
*/
|
||||
|
||||
txt_inputbox_t *TXT_NewInputBox(char **value, int size);
|
||||
|
||||
/**
|
||||
* Create a new input box widget for controlling an integer value.
|
||||
*
|
||||
* @param value Pointer to an integer variable containing
|
||||
* the value of the input box.
|
||||
* @param size Width of the input box, in characters.
|
||||
* @return Pointer to the new input box widget.
|
||||
*/
|
||||
|
||||
txt_inputbox_t *TXT_NewIntInputBox(int *value, int size);
|
||||
|
||||
/**
|
||||
* Create a new input box widget for controlling a string value
|
||||
* with custom draw size.
|
||||
*
|
||||
* @param value Pointer to a string variable that contains
|
||||
* a pointer to the current value of the
|
||||
* input box. The value should be allocated
|
||||
* dynamically; when the string is changed it
|
||||
* will be freed and the variable set to point
|
||||
* to the new string value. String will be in
|
||||
* UTF-8 format.
|
||||
* @param size Maximum number of characters that can be entered.
|
||||
* @param drawsize Draw width of the input box, in characters.
|
||||
* @return Pointer to the new input box widget.
|
||||
*/
|
||||
|
||||
txt_inputbox_t* TXT_NewInputBoxCustomSize(char** value, int size, int drawsize);
|
||||
|
||||
/**
|
||||
* Create a new input box widget for controlling an integer value
|
||||
* with custom draw size.
|
||||
*
|
||||
* @param value Pointer to an integer variable containing
|
||||
* the value of the input box.
|
||||
* @param size Maximum number of characters that can be entered.
|
||||
* @param drawsize Draw width of the input box, in characters.
|
||||
* @return Pointer to the new input box widget.
|
||||
*/
|
||||
|
||||
txt_inputbox_t* TXT_NewIntInputBoxCustomSize(int* value, int size, int drawsize);
|
||||
|
||||
#endif /* #ifndef TXT_INPUTBOX_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Text mode I/O functions, similar to C stdio
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
|
||||
static int cur_x = 0, cur_y = 0;
|
||||
static txt_color_t fgcolor = TXT_COLOR_GREY;
|
||||
static txt_color_t bgcolor = TXT_COLOR_BLACK;
|
||||
|
||||
static void NewLine(unsigned char *screendata)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p;
|
||||
|
||||
cur_x = 0;
|
||||
++cur_y;
|
||||
|
||||
if (cur_y >= TXT_SCREEN_H)
|
||||
{
|
||||
// Scroll the screen up
|
||||
|
||||
cur_y = TXT_SCREEN_H - 1;
|
||||
|
||||
memmove(screendata, screendata + TXT_SCREEN_W * 2,
|
||||
TXT_SCREEN_W * 2 * (TXT_SCREEN_H -1));
|
||||
|
||||
// Clear the bottom line
|
||||
|
||||
p = screendata + (TXT_SCREEN_H - 1) * 2 * TXT_SCREEN_W;
|
||||
|
||||
for (i=0; i<TXT_SCREEN_W; ++i)
|
||||
{
|
||||
*p++ = ' ';
|
||||
*p++ = fgcolor | (bgcolor << 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PutSymbol(unsigned char *screendata, int c)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
p = screendata + cur_y * TXT_SCREEN_W * 2 + cur_x * 2;
|
||||
|
||||
// Add a new character to the buffer
|
||||
|
||||
p[0] = c;
|
||||
p[1] = fgcolor | (bgcolor << 4);
|
||||
|
||||
++cur_x;
|
||||
|
||||
if (cur_x >= TXT_SCREEN_W)
|
||||
{
|
||||
NewLine(screendata);
|
||||
}
|
||||
}
|
||||
|
||||
// "Blind" version of TXT_PutChar() below which doesn't do any interpretation
|
||||
// of control signals. Just write a particular symbol to the screen buffer.
|
||||
void TXT_PutSymbol(int c)
|
||||
{
|
||||
PutSymbol(TXT_GetScreenData(), c);
|
||||
}
|
||||
|
||||
static void PutChar(unsigned char *screendata, int c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
NewLine(screendata);
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
// backspace
|
||||
--cur_x;
|
||||
if (cur_x < 0)
|
||||
cur_x = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
PutSymbol(screendata, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TXT_PutChar(int c)
|
||||
{
|
||||
PutChar(TXT_GetScreenData(), c);
|
||||
}
|
||||
|
||||
void TXT_Puts(const char *s)
|
||||
{
|
||||
unsigned char *screen;
|
||||
const char *p;
|
||||
|
||||
screen = TXT_GetScreenData();
|
||||
|
||||
for (p=s; *p != '\0'; ++p)
|
||||
{
|
||||
PutChar(screen, *p);
|
||||
}
|
||||
|
||||
PutChar(screen, '\n');
|
||||
}
|
||||
|
||||
void TXT_GotoXY(int x, int y)
|
||||
{
|
||||
cur_x = x;
|
||||
cur_y = y;
|
||||
}
|
||||
|
||||
void TXT_GetXY(int *x, int *y)
|
||||
{
|
||||
*x = cur_x;
|
||||
*y = cur_y;
|
||||
}
|
||||
|
||||
void TXT_FGColor(txt_color_t color)
|
||||
{
|
||||
fgcolor = color;
|
||||
}
|
||||
|
||||
void TXT_BGColor(int color, int blinking)
|
||||
{
|
||||
bgcolor = color;
|
||||
if (blinking)
|
||||
bgcolor |= TXT_COLOR_BLINKING;
|
||||
}
|
||||
|
||||
void TXT_SaveColors(txt_saved_colors_t *save)
|
||||
{
|
||||
save->bgcolor = bgcolor;
|
||||
save->fgcolor = fgcolor;
|
||||
}
|
||||
|
||||
void TXT_RestoreColors(txt_saved_colors_t *save)
|
||||
{
|
||||
bgcolor = save->bgcolor;
|
||||
fgcolor = save->fgcolor;
|
||||
}
|
||||
|
||||
void TXT_ClearScreen(void)
|
||||
{
|
||||
unsigned char *screen;
|
||||
int i;
|
||||
|
||||
screen = TXT_GetScreenData();
|
||||
|
||||
for (i=0; i<TXT_SCREEN_W * TXT_SCREEN_H; ++i)
|
||||
{
|
||||
screen[i * 2] = ' ';
|
||||
screen[i * 2 + 1] = (bgcolor << 4) | fgcolor;
|
||||
}
|
||||
|
||||
cur_x = 0;
|
||||
cur_y = 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Text mode emulation in SDL
|
||||
//
|
||||
|
||||
#ifndef TXT_IO_H
|
||||
#define TXT_IO_H
|
||||
|
||||
#include "txt_main.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int bgcolor;
|
||||
int fgcolor;
|
||||
} txt_saved_colors_t;
|
||||
|
||||
void TXT_PutSymbol(int c);
|
||||
void TXT_PutChar(int c);
|
||||
void TXT_Puts(const char *s);
|
||||
void TXT_GotoXY(int x, int y);
|
||||
void TXT_GetXY(int *x, int *y);
|
||||
void TXT_FGColor(txt_color_t color);
|
||||
void TXT_BGColor(int color, int blinking);
|
||||
void TXT_SaveColors(txt_saved_colors_t *save);
|
||||
void TXT_RestoreColors(txt_saved_colors_t *save);
|
||||
void TXT_ClearScreen(void);
|
||||
|
||||
#endif /* #ifndef TXT_IO_H */
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "txt_label.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
static void TXT_LabelSizeCalc(TXT_UNCAST_ARG(label))
|
||||
{
|
||||
TXT_CAST_ARG(txt_label_t, label);
|
||||
|
||||
label->widget.w = label->w;
|
||||
label->widget.h = label->h;
|
||||
}
|
||||
|
||||
static void TXT_LabelDrawer(TXT_UNCAST_ARG(label))
|
||||
{
|
||||
TXT_CAST_ARG(txt_label_t, label);
|
||||
unsigned int x, y;
|
||||
int origin_x, origin_y;
|
||||
unsigned int align_indent = 0;
|
||||
unsigned int w, sw;
|
||||
|
||||
w = label->widget.w;
|
||||
|
||||
if (label->bgcolor >= 0)
|
||||
{
|
||||
TXT_BGColor(label->bgcolor, 0);
|
||||
}
|
||||
if (label->fgcolor >= 0)
|
||||
{
|
||||
TXT_FGColor(label->fgcolor);
|
||||
}
|
||||
|
||||
TXT_GetXY(&origin_x, &origin_y);
|
||||
|
||||
for (y=0; y<label->h; ++y)
|
||||
{
|
||||
// Calculate the amount to indent this line due to the align
|
||||
// setting
|
||||
sw = TXT_UTF8_Strlen(label->lines[y]);
|
||||
switch (label->widget.align)
|
||||
{
|
||||
case TXT_HORIZ_LEFT:
|
||||
align_indent = 0;
|
||||
break;
|
||||
case TXT_HORIZ_CENTER:
|
||||
align_indent = (label->w - sw) / 2;
|
||||
break;
|
||||
case TXT_HORIZ_RIGHT:
|
||||
align_indent = label->w - sw;
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw this line
|
||||
|
||||
if (label->customlabel == 1)
|
||||
TXT_GotoXY(origin_x + 1, origin_y + y);
|
||||
else
|
||||
TXT_GotoXY(origin_x, origin_y + y);
|
||||
|
||||
// Gap at the start
|
||||
|
||||
for (x=0; x<align_indent; ++x)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
|
||||
// The string itself
|
||||
|
||||
TXT_DrawString(label->lines[y]);
|
||||
x += sw;
|
||||
|
||||
// Gap at the end
|
||||
|
||||
for (; x<w; ++x)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_LabelDestructor(TXT_UNCAST_ARG(label))
|
||||
{
|
||||
TXT_CAST_ARG(txt_label_t, label);
|
||||
|
||||
free(label->label);
|
||||
free(label->lines);
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_label_class =
|
||||
{
|
||||
TXT_NeverSelectable,
|
||||
TXT_LabelSizeCalc,
|
||||
TXT_LabelDrawer,
|
||||
NULL,
|
||||
TXT_LabelDestructor,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void TXT_SetLabel(txt_label_t *label, const char *value)
|
||||
{
|
||||
char *p;
|
||||
unsigned int y;
|
||||
|
||||
// Free back the old label
|
||||
|
||||
free(label->label);
|
||||
free(label->lines);
|
||||
|
||||
// Set the new value
|
||||
|
||||
label->label = strdup(value);
|
||||
|
||||
// Work out how many lines in this label
|
||||
|
||||
label->h = 1;
|
||||
|
||||
for (p = label->label; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == '\n')
|
||||
{
|
||||
++label->h;
|
||||
}
|
||||
}
|
||||
|
||||
// Split into lines
|
||||
|
||||
label->lines = malloc(sizeof(char *) * label->h);
|
||||
label->lines[0] = label->label;
|
||||
y = 1;
|
||||
|
||||
for (p = label->label; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == '\n')
|
||||
{
|
||||
label->lines[y] = p + 1;
|
||||
*p = '\0';
|
||||
++y;
|
||||
}
|
||||
}
|
||||
|
||||
label->w = 0;
|
||||
|
||||
for (y=0; y<label->h; ++y)
|
||||
{
|
||||
unsigned int line_len;
|
||||
|
||||
line_len = TXT_UTF8_Strlen(label->lines[y]);
|
||||
|
||||
if (line_len > label->w)
|
||||
label->w = line_len;
|
||||
}
|
||||
}
|
||||
|
||||
txt_label_t* TXT_NewSpecialLabel(const char* text)
|
||||
{
|
||||
txt_label_t* label;
|
||||
|
||||
label = malloc(sizeof(txt_label_t));
|
||||
|
||||
TXT_InitWidget(label, &txt_label_class);
|
||||
label->label = NULL;
|
||||
label->lines = NULL;
|
||||
|
||||
// Default colors
|
||||
|
||||
label->bgcolor = -1;
|
||||
label->fgcolor = -1;
|
||||
|
||||
label->customlabel = 1;
|
||||
|
||||
TXT_SetLabel(label, text);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
txt_label_t *TXT_NewLabel(const char *text)
|
||||
{
|
||||
txt_label_t *label;
|
||||
|
||||
label = malloc(sizeof(txt_label_t));
|
||||
|
||||
TXT_InitWidget(label, &txt_label_class);
|
||||
label->label = NULL;
|
||||
label->lines = NULL;
|
||||
|
||||
// Default colors
|
||||
|
||||
label->bgcolor = -1;
|
||||
label->fgcolor = -1;
|
||||
|
||||
label->customlabel = 0;
|
||||
|
||||
TXT_SetLabel(label, text);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
void TXT_SetFGColor(txt_label_t *label, txt_color_t color)
|
||||
{
|
||||
label->fgcolor = color;
|
||||
}
|
||||
|
||||
void TXT_SetBGColor(txt_label_t *label, txt_color_t color)
|
||||
{
|
||||
label->bgcolor = color;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_LABEL_H
|
||||
#define TXT_LABEL_H
|
||||
|
||||
/**
|
||||
* @file txt_label.h
|
||||
*
|
||||
* Text label widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Label widget.
|
||||
*
|
||||
* A label widget does nothing except show a text label.
|
||||
*/
|
||||
|
||||
typedef struct txt_label_s txt_label_t;
|
||||
|
||||
#include "txt_main.h"
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_label_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
char *label;
|
||||
char **lines;
|
||||
unsigned int w, h;
|
||||
int fgcolor;
|
||||
int bgcolor;
|
||||
int customlabel;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new label widget.
|
||||
*
|
||||
* @param label String to display in the widget (UTF-8 format).
|
||||
* @return Pointer to the new label widget.
|
||||
*/
|
||||
|
||||
txt_label_t *TXT_NewLabel(const char *label);
|
||||
|
||||
/**
|
||||
* Create a new label widget at position +1 on x axis.
|
||||
*
|
||||
* @param label String to display in the widget (UTF-8 format).
|
||||
* @return Pointer to the new label widget.
|
||||
*/
|
||||
|
||||
txt_label_t* TXT_NewSpecialLabel(const char* label);
|
||||
|
||||
/**
|
||||
* Set the string displayed in a label widget.
|
||||
*
|
||||
* @param label The widget.
|
||||
* @param value The string to display (UTF-8 format).
|
||||
*/
|
||||
|
||||
void TXT_SetLabel(txt_label_t *label, const char *value);
|
||||
|
||||
/**
|
||||
* Set the background color of a label widget.
|
||||
*
|
||||
* @param label The widget.
|
||||
* @param color The background color to use.
|
||||
*/
|
||||
|
||||
void TXT_SetBGColor(txt_label_t *label, txt_color_t color);
|
||||
|
||||
/**
|
||||
* Set the foreground color of a label widget.
|
||||
*
|
||||
* @param label The widget.
|
||||
* @param color The foreground color to use.
|
||||
*/
|
||||
|
||||
void TXT_SetFGColor(txt_label_t *label, txt_color_t color);
|
||||
|
||||
#endif /* #ifndef TXT_LABEL_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Base interface that abstracts the text mode screen.
|
||||
//
|
||||
|
||||
#ifndef TXT_MAIN_H
|
||||
#define TXT_MAIN_H
|
||||
|
||||
// For the moment, txt_sdl.c is the only implementation of the base
|
||||
// text mode screen API:
|
||||
|
||||
#include "txt_sdl.h"
|
||||
|
||||
// textscreen key values:
|
||||
// Key values are difficult because we have to support multiple conflicting
|
||||
// address spaces.
|
||||
// First, Doom's key constants use 0-127 as ASCII and extra values from
|
||||
// 128-255 to represent special keys. Second, mouse buttons are represented
|
||||
// as buttons. Finally, we want to be able to support Unicode.
|
||||
//
|
||||
// So we define different ranges:
|
||||
// 0-255: Doom key constants, including ASCII.
|
||||
// 256-511: Mouse buttons and other reserved.
|
||||
// >=512: Unicode values greater than 127 are offset up into this range.
|
||||
|
||||
// Special keypress values that correspond to mouse button clicks
|
||||
|
||||
#define TXT_MOUSE_BASE 256
|
||||
#define TXT_MOUSE_LEFT (TXT_MOUSE_BASE + 0)
|
||||
#define TXT_MOUSE_RIGHT (TXT_MOUSE_BASE + 1)
|
||||
#define TXT_MOUSE_MIDDLE (TXT_MOUSE_BASE + 2)
|
||||
#define TXT_MOUSE_SCROLLUP (TXT_MOUSE_BASE + 3)
|
||||
#define TXT_MOUSE_SCROLLDOWN (TXT_MOUSE_BASE + 4)
|
||||
#define TXT_MAX_MOUSE_BUTTONS 16
|
||||
|
||||
#define TXT_KEY_TO_MOUSE_BUTTON(x) \
|
||||
( (x) >= TXT_MOUSE_BASE \
|
||||
&& (x) < TXT_MOUSE_BASE + TXT_MAX_MOUSE_BUTTONS ? \
|
||||
(x) - TXT_MOUSE_BASE : -1 )
|
||||
|
||||
// Unicode offset. Unicode values from 128 onwards are offset up into
|
||||
// this range, so TXT_UNICODE_BASE = Unicode character #128, and so on.
|
||||
|
||||
#define TXT_UNICODE_BASE 512
|
||||
|
||||
// Convert a key value to a Unicode character:
|
||||
|
||||
#define TXT_KEY_TO_UNICODE(x) \
|
||||
( (x) < 128 ? (x) : \
|
||||
(x) >= TXT_UNICODE_BASE ? ((x) - TXT_UNICODE_BASE + 128) : 0 )
|
||||
|
||||
// Convert a Unicode character to a key value:
|
||||
|
||||
#define TXT_UNICODE_TO_KEY(u) \
|
||||
( (u) < 128 ? (u) : ((u) - 128 + TXT_UNICODE_BASE) )
|
||||
|
||||
// Screen size
|
||||
|
||||
#define TXT_SCREEN_W 80
|
||||
#define TXT_SCREEN_H 25
|
||||
|
||||
#define TXT_COLOR_BLINKING (1 << 3)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TXT_COLOR_BLACK,
|
||||
TXT_COLOR_BLUE,
|
||||
TXT_COLOR_GREEN,
|
||||
TXT_COLOR_CYAN,
|
||||
TXT_COLOR_RED,
|
||||
TXT_COLOR_MAGENTA,
|
||||
TXT_COLOR_BROWN,
|
||||
TXT_COLOR_GREY,
|
||||
TXT_COLOR_DARK_GREY,
|
||||
TXT_COLOR_BRIGHT_BLUE,
|
||||
TXT_COLOR_BRIGHT_GREEN,
|
||||
TXT_COLOR_BRIGHT_CYAN,
|
||||
TXT_COLOR_BRIGHT_RED,
|
||||
TXT_COLOR_BRIGHT_MAGENTA,
|
||||
TXT_COLOR_YELLOW,
|
||||
TXT_COLOR_BRIGHT_WHITE,
|
||||
} txt_color_t;
|
||||
|
||||
// Modifier keys.
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TXT_MOD_SHIFT,
|
||||
TXT_MOD_CTRL,
|
||||
TXT_MOD_ALT,
|
||||
TXT_NUM_MODIFIERS
|
||||
} txt_modifier_t;
|
||||
|
||||
// Due to the way the SDL API works, we provide different ways of configuring
|
||||
// how we read input events, each of which is useful in different scenarios.
|
||||
typedef enum
|
||||
{
|
||||
// "Localized" output that takes software keyboard layout into account,
|
||||
// but key shifting has no effect.
|
||||
TXT_INPUT_NORMAL,
|
||||
|
||||
// "Raw" input; the keys correspond to physical keyboard layout and
|
||||
// software keyboard layout has no effect.
|
||||
TXT_INPUT_RAW,
|
||||
|
||||
// Used for full text input. Events are fully shifted and localized.
|
||||
// However, not all keyboard keys will generate input.
|
||||
// Setting this mode may activate the on-screen keyboard, depending on
|
||||
// device and OS.
|
||||
TXT_INPUT_TEXT,
|
||||
} txt_input_mode_t;
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#define PRINTF_ATTR(fmt, first) __attribute__((format(printf, fmt, first)))
|
||||
|
||||
#else // __GNUC__
|
||||
|
||||
#define PRINTF_ATTR(fmt, first)
|
||||
|
||||
#endif // __GNUC__
|
||||
|
||||
// Initialize the screen
|
||||
// Returns 1 if successful, 0 if failed.
|
||||
int TXT_Init(void);
|
||||
|
||||
// Shut down text mode emulation
|
||||
void TXT_Shutdown(void);
|
||||
|
||||
// Get a pointer to the buffer containing the raw screen data.
|
||||
unsigned char *TXT_GetScreenData(void);
|
||||
|
||||
// Update an area of the screen
|
||||
void TXT_UpdateScreenArea(int x, int y, int w, int h);
|
||||
|
||||
// Update the whole screen
|
||||
void TXT_UpdateScreen(void);
|
||||
|
||||
// Set the RGB value for a particular entry in the color palette:
|
||||
void TXT_SetColor(txt_color_t color, int r, int g, int b);
|
||||
|
||||
// Read a character from the keyboard
|
||||
int TXT_GetChar(void);
|
||||
|
||||
// Given a Unicode character, get a character that can be used to represent
|
||||
// it on the code page being displayed on the screen. If the character cannot
|
||||
// be represented, this returns -1.
|
||||
int TXT_UnicodeCharacter(unsigned int c);
|
||||
|
||||
// Read the current state of modifier keys that are held down.
|
||||
int TXT_GetModifierState(txt_modifier_t mod);
|
||||
|
||||
// Provides a short description of a key code, placing into the provided
|
||||
// buffer. Note that the key is assumed to represent a physical key on the
|
||||
// keyboard (like that returned by TXT_INPUT_RAW), and the resulting string
|
||||
// takes keyboard layout into consideration. For example,
|
||||
// TXT_GetKeyDescription('q') on a French keyboard returns "A".
|
||||
// The contents of the filled buffer will be in UTF-8 format, but will never
|
||||
// contain characters which can't be shown on the screen.
|
||||
void TXT_GetKeyDescription(int key, char *buf, size_t buf_len);
|
||||
|
||||
// Retrieve the current position of the mouse
|
||||
void TXT_GetMousePosition(int *x, int *y);
|
||||
|
||||
// Sleep until an event is received or the screen needs updating
|
||||
// Optional timeout in ms (timeout == 0 : sleep forever)
|
||||
void TXT_Sleep(int timeout);
|
||||
|
||||
// Change mode for text input.
|
||||
void TXT_SetInputMode(txt_input_mode_t mode);
|
||||
|
||||
// Set the window title of the window containing the text mode screen
|
||||
void TXT_SetWindowTitle(const char *title);
|
||||
|
||||
// Safe string copy.
|
||||
void TXT_StringCopy(char *dest, const char *src, size_t dest_len);
|
||||
|
||||
// Safe string concatenate.
|
||||
void TXT_StringConcat(char *dest, const char *src, size_t dest_len);
|
||||
|
||||
// Safe version of vsnprintf().
|
||||
int TXT_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args);
|
||||
|
||||
// Safe version of snprintf().
|
||||
int TXT_snprintf(char *buf, size_t buf_len, const char *s, ...) PRINTF_ATTR(3, 4);
|
||||
|
||||
// Set fullscreenmode
|
||||
void TXT_Fullscreen(int fullscreen);
|
||||
|
||||
#endif /* #ifndef TXT_MAIN_H */
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_radiobutton.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
static void TXT_RadioButtonSizeCalc(TXT_UNCAST_ARG(radiobutton))
|
||||
{
|
||||
TXT_CAST_ARG(txt_radiobutton_t, radiobutton);
|
||||
|
||||
// Minimum width is the string length + right-side spaces for padding
|
||||
|
||||
radiobutton->widget.w = TXT_UTF8_Strlen(radiobutton->label) + 5;
|
||||
radiobutton->widget.h = 1;
|
||||
}
|
||||
|
||||
static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton))
|
||||
{
|
||||
TXT_CAST_ARG(txt_radiobutton_t, radiobutton);
|
||||
txt_saved_colors_t colors;
|
||||
int i;
|
||||
int w;
|
||||
|
||||
w = radiobutton->widget.w;
|
||||
|
||||
TXT_SaveColors(&colors);
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
TXT_DrawString("(");
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
|
||||
|
||||
if (*radiobutton->variable == radiobutton->value)
|
||||
{
|
||||
TXT_DrawCodePageString("\x07");
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
|
||||
TXT_DrawString(") ");
|
||||
|
||||
TXT_RestoreColors(&colors);
|
||||
TXT_SetWidgetBG(radiobutton);
|
||||
|
||||
TXT_DrawString(radiobutton->label);
|
||||
|
||||
for (i=TXT_UTF8_Strlen(radiobutton->label); i < w-5; ++i)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_RadioButtonDestructor(TXT_UNCAST_ARG(radiobutton))
|
||||
{
|
||||
TXT_CAST_ARG(txt_radiobutton_t, radiobutton);
|
||||
|
||||
free(radiobutton->label);
|
||||
}
|
||||
|
||||
static int TXT_RadioButtonKeyPress(TXT_UNCAST_ARG(radiobutton), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_radiobutton_t, radiobutton);
|
||||
|
||||
if (key == KEY_ENTER || key == ' ')
|
||||
{
|
||||
if (*radiobutton->variable != radiobutton->value)
|
||||
{
|
||||
*radiobutton->variable = radiobutton->value;
|
||||
TXT_EmitSignal(radiobutton, "selected");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TXT_RadioButtonMousePress(TXT_UNCAST_ARG(radiobutton),
|
||||
int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_radiobutton_t, radiobutton);
|
||||
|
||||
if (b == TXT_MOUSE_LEFT)
|
||||
{
|
||||
// Equivalent to pressing enter
|
||||
|
||||
TXT_RadioButtonKeyPress(radiobutton, KEY_ENTER);
|
||||
}
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_radiobutton_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_RadioButtonSizeCalc,
|
||||
TXT_RadioButtonDrawer,
|
||||
TXT_RadioButtonKeyPress,
|
||||
TXT_RadioButtonDestructor,
|
||||
TXT_RadioButtonMousePress,
|
||||
NULL,
|
||||
};
|
||||
|
||||
txt_radiobutton_t *TXT_NewRadioButton(const char *label, int *variable, int value)
|
||||
{
|
||||
txt_radiobutton_t *radiobutton;
|
||||
|
||||
radiobutton = malloc(sizeof(txt_radiobutton_t));
|
||||
|
||||
TXT_InitWidget(radiobutton, &txt_radiobutton_class);
|
||||
radiobutton->label = strdup(label);
|
||||
radiobutton->variable = variable;
|
||||
radiobutton->value = value;
|
||||
|
||||
return radiobutton;
|
||||
}
|
||||
|
||||
void TXT_SetRadioButtonLabel(txt_radiobutton_t *radiobutton, const char *value)
|
||||
{
|
||||
free(radiobutton->label);
|
||||
radiobutton->label = strdup(value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_RADIOBUTTON_H
|
||||
#define TXT_RADIOBUTTON_H
|
||||
|
||||
/**
|
||||
* @file txt_radiobutton.h
|
||||
*
|
||||
* Radio button widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A radio button widget.
|
||||
*
|
||||
* Radio buttons are typically used in groups, to allow a value to be
|
||||
* selected from a range of options. Each radio button corresponds
|
||||
* to a particular option that may be selected. A radio button
|
||||
* has an indicator to indicate whether it is the currently-selected
|
||||
* value, and a text label.
|
||||
*
|
||||
* Internally, a radio button tracks an integer variable that may take
|
||||
* a range of different values. Each radio button has a particular
|
||||
* value associated with it; if the variable is equal to that value,
|
||||
* the radio button appears selected. If a radio button is pressed
|
||||
* by the user through the GUI, the variable is set to its value.
|
||||
*
|
||||
* When a radio button is selected, the "selected" signal is emitted.
|
||||
*/
|
||||
|
||||
typedef struct txt_radiobutton_s txt_radiobutton_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_radiobutton_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
char *label;
|
||||
int *variable;
|
||||
int value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new radio button widget.
|
||||
*
|
||||
* @param label The label to display next to the radio button
|
||||
* (UTF-8 format).
|
||||
* @param variable Pointer to the variable tracking whether this
|
||||
* radio button is selected.
|
||||
* @param value If the variable is equal to this value, the
|
||||
* radio button appears selected.
|
||||
* @return Pointer to the new radio button widget.
|
||||
*/
|
||||
|
||||
txt_radiobutton_t *TXT_NewRadioButton(const char *label, int *variable, int value);
|
||||
|
||||
/**
|
||||
* Set the label on a radio button.
|
||||
*
|
||||
* @param radiobutton The radio button.
|
||||
* @param value The new label (UTF-8 format).
|
||||
*/
|
||||
|
||||
void TXT_SetRadioButtonLabel(txt_radiobutton_t *radiobutton, const char *value);
|
||||
|
||||
#endif /* #ifndef TXT_RADIOBUTTON_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,586 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "txt_scrollpane.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_table.h"
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#define SCROLLBAR_VERTICAL (1 << 0)
|
||||
#define SCROLLBAR_HORIZONTAL (1 << 1)
|
||||
|
||||
static int FullWidth(txt_scrollpane_t *scrollpane)
|
||||
{
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
return scrollpane->child->w;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int FullHeight(txt_scrollpane_t *scrollpane)
|
||||
{
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
return scrollpane->child->h;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate which scroll bars the pane needs.
|
||||
|
||||
static int NeedsScrollbars(txt_scrollpane_t *scrollpane)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = 0;
|
||||
|
||||
if (FullWidth(scrollpane) > scrollpane->w)
|
||||
{
|
||||
result |= SCROLLBAR_HORIZONTAL;
|
||||
}
|
||||
if (FullHeight(scrollpane) > scrollpane->h)
|
||||
{
|
||||
result |= SCROLLBAR_VERTICAL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// If a scrollbar isn't needed, the scroll position is reset.
|
||||
|
||||
static void SanityCheckScrollbars(txt_scrollpane_t *scrollpane)
|
||||
{
|
||||
int scrollbars;
|
||||
int max_x, max_y;
|
||||
|
||||
scrollbars = NeedsScrollbars(scrollpane);
|
||||
|
||||
if ((scrollbars & SCROLLBAR_HORIZONTAL) == 0)
|
||||
{
|
||||
scrollpane->x = 0;
|
||||
}
|
||||
if ((scrollbars & SCROLLBAR_VERTICAL) == 0)
|
||||
{
|
||||
scrollpane->y = 0;
|
||||
}
|
||||
|
||||
max_x = FullWidth(scrollpane) - scrollpane->w;
|
||||
max_y = FullHeight(scrollpane) - scrollpane->h;
|
||||
|
||||
if (scrollpane->x < 0)
|
||||
{
|
||||
scrollpane->x = 0;
|
||||
}
|
||||
else if (scrollpane->x > max_x)
|
||||
{
|
||||
scrollpane->x = max_x;
|
||||
}
|
||||
|
||||
if (scrollpane->y < 0)
|
||||
{
|
||||
scrollpane->y = 0;
|
||||
}
|
||||
else if (scrollpane->y > max_y)
|
||||
{
|
||||
scrollpane->y = max_y;
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_ScrollPaneSizeCalc(TXT_UNCAST_ARG(scrollpane))
|
||||
{
|
||||
TXT_CAST_ARG(txt_scrollpane_t, scrollpane);
|
||||
int scrollbars;
|
||||
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
TXT_CalcWidgetSize(scrollpane->child);
|
||||
}
|
||||
|
||||
// Expand as necessary (to ensure that no scrollbars are needed)?
|
||||
|
||||
if (scrollpane->expand_w)
|
||||
{
|
||||
scrollpane->w = FullWidth(scrollpane);
|
||||
}
|
||||
if (scrollpane->expand_h)
|
||||
{
|
||||
scrollpane->h = FullHeight(scrollpane);
|
||||
}
|
||||
|
||||
scrollpane->widget.w = scrollpane->w;
|
||||
scrollpane->widget.h = scrollpane->h;
|
||||
|
||||
// If we have scroll bars, we need to expand slightly to
|
||||
// accomodate them. Eg. if we have a vertical scrollbar, we
|
||||
// need to be an extra character wide.
|
||||
|
||||
scrollbars = NeedsScrollbars(scrollpane);
|
||||
|
||||
if (scrollbars & SCROLLBAR_HORIZONTAL)
|
||||
{
|
||||
++scrollpane->widget.h;
|
||||
}
|
||||
if (scrollbars & SCROLLBAR_VERTICAL)
|
||||
{
|
||||
++scrollpane->widget.w;
|
||||
}
|
||||
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
if (scrollpane->child->w < scrollpane->w)
|
||||
{
|
||||
scrollpane->child->w = scrollpane->w;
|
||||
}
|
||||
if (scrollpane->child->h < scrollpane->h)
|
||||
{
|
||||
scrollpane->child->h = scrollpane->h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_ScrollPaneDrawer(TXT_UNCAST_ARG(scrollpane))
|
||||
{
|
||||
TXT_CAST_ARG(txt_scrollpane_t, scrollpane);
|
||||
int x1, y1, x2, y2;
|
||||
int scrollbars;
|
||||
|
||||
// We set a clipping area of the scroll pane.
|
||||
|
||||
x1 = scrollpane->widget.x,
|
||||
y1 = scrollpane->widget.y,
|
||||
x2 = x1 + scrollpane->w,
|
||||
y2 = y1 + scrollpane->h;
|
||||
|
||||
scrollbars = NeedsScrollbars(scrollpane);
|
||||
|
||||
if (scrollbars & SCROLLBAR_HORIZONTAL)
|
||||
{
|
||||
TXT_DrawHorizScrollbar(x1,
|
||||
y1 + scrollpane->h,
|
||||
scrollpane->w,
|
||||
scrollpane->x,
|
||||
FullWidth(scrollpane) - scrollpane->w);
|
||||
}
|
||||
|
||||
if (scrollbars & SCROLLBAR_VERTICAL)
|
||||
{
|
||||
TXT_DrawVertScrollbar(x1 + scrollpane->w,
|
||||
y1,
|
||||
scrollpane->h,
|
||||
scrollpane->y,
|
||||
FullHeight(scrollpane) - scrollpane->h);
|
||||
}
|
||||
|
||||
TXT_PushClipArea(x1, x2, y1, y2);
|
||||
|
||||
// Draw the child widget
|
||||
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
TXT_DrawWidget(scrollpane->child);
|
||||
}
|
||||
|
||||
// Restore old clipping area.
|
||||
|
||||
TXT_PopClipArea();
|
||||
}
|
||||
|
||||
static void TXT_ScrollPaneDestructor(TXT_UNCAST_ARG(scrollpane))
|
||||
{
|
||||
TXT_CAST_ARG(txt_scrollpane_t, scrollpane);
|
||||
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
TXT_DestroyWidget(scrollpane->child);
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_ScrollPaneFocused(TXT_UNCAST_ARG(scrollpane), int focused)
|
||||
{
|
||||
TXT_CAST_ARG(txt_scrollpane_t, scrollpane);
|
||||
|
||||
// Whether the child is focused depends only on whether the scroll pane
|
||||
// itself is focused. Pass through focus to the child.
|
||||
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
TXT_SetWidgetFocus(scrollpane->child, focused);
|
||||
}
|
||||
}
|
||||
|
||||
// Hack for tables - when browsing a table inside a scroll pane,
|
||||
// automatically scroll the window to show the newly-selected
|
||||
// item.
|
||||
|
||||
static void ShowSelectedWidget(txt_scrollpane_t *scrollpane)
|
||||
{
|
||||
txt_widget_t *selected;
|
||||
|
||||
selected = TXT_GetSelectedWidget(scrollpane->child);
|
||||
|
||||
// Scroll up or down?
|
||||
|
||||
if (selected->y <= scrollpane->widget.y)
|
||||
{
|
||||
scrollpane->y -= scrollpane->widget.y - selected->y;
|
||||
}
|
||||
else if ((signed) (selected->y + selected->h) >
|
||||
(signed) (scrollpane->widget.y + scrollpane->h))
|
||||
{
|
||||
scrollpane->y += (selected->y + selected->h)
|
||||
- (scrollpane->widget.y + scrollpane->h);
|
||||
}
|
||||
|
||||
// Scroll left or right?
|
||||
|
||||
if (selected->x <= scrollpane->widget.x)
|
||||
{
|
||||
scrollpane->x -= scrollpane->widget.x - selected->x;
|
||||
}
|
||||
else if ((signed) (selected->x + selected->w) >
|
||||
(signed) (scrollpane->widget.x + scrollpane->w))
|
||||
{
|
||||
scrollpane->x += (selected->x + selected->w)
|
||||
- (scrollpane->widget.x + scrollpane->w);
|
||||
}
|
||||
}
|
||||
|
||||
// Another hack for tables - when scrolling in 'pages', the normal key press
|
||||
// event does not provide children with enough information to know how far
|
||||
// to move their selection to reach a new page. This function does so.
|
||||
// Note that it *only* affects scrolling in pages, not with arrows!
|
||||
// A side-effect of this, rather than 'pulling' the selection to fit within
|
||||
// the new page, is that we will jump straight over ranges of unselectable
|
||||
// items longer than a page, but that is also true of arrow-key scrolling.
|
||||
// The other unfortunate effect of doing things this way is that page keys
|
||||
// have no effect on tables _not_ in scrollpanes: not even home/end.
|
||||
|
||||
static int PageSelectedWidget(txt_scrollpane_t *scrollpane, int key)
|
||||
{
|
||||
int pagex = 0; // No page left/right yet, but some keyboards have them
|
||||
int pagey = 0;
|
||||
|
||||
// Subtract one from the absolute page distance as this is slightly more
|
||||
// intuitive: a page down first jumps to the bottom of the current page,
|
||||
// then proceeds to scroll onwards.
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case KEY_PGUP:
|
||||
pagey = 1 - scrollpane->h;
|
||||
break;
|
||||
|
||||
case KEY_PGDN:
|
||||
pagey = scrollpane->h - 1;
|
||||
break;
|
||||
|
||||
default: // We shouldn't even be in this function
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (scrollpane->child->widget_class == &txt_table_class)
|
||||
{
|
||||
return TXT_PageTable(scrollpane->child, pagex, pagey);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Interpret arrow key presses as scroll commands
|
||||
|
||||
static int InterpretScrollKey(txt_scrollpane_t *scrollpane, int key)
|
||||
{
|
||||
int maxy;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case KEY_UPARROW:
|
||||
if (scrollpane->y > 0)
|
||||
{
|
||||
--scrollpane->y;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_DOWNARROW:
|
||||
if (scrollpane->y < FullHeight(scrollpane) - scrollpane->h)
|
||||
{
|
||||
++scrollpane->y;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_LEFTARROW:
|
||||
if (scrollpane->x > 0)
|
||||
{
|
||||
--scrollpane->x;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_RIGHTARROW:
|
||||
if (scrollpane->x < FullWidth(scrollpane) - scrollpane->w)
|
||||
{
|
||||
++scrollpane->x;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_PGUP:
|
||||
if (scrollpane->y > 0)
|
||||
{
|
||||
scrollpane->y -= scrollpane->h;
|
||||
if (scrollpane->y < 0)
|
||||
{
|
||||
scrollpane->y = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_PGDN:
|
||||
maxy = FullHeight(scrollpane) - scrollpane->h;
|
||||
if (scrollpane->y < maxy)
|
||||
{
|
||||
scrollpane->y += scrollpane->h;
|
||||
if (scrollpane->y > maxy)
|
||||
{
|
||||
scrollpane->y = maxy;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int TXT_ScrollPaneKeyPress(TXT_UNCAST_ARG(scrollpane), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_scrollpane_t, scrollpane);
|
||||
int result;
|
||||
|
||||
result = 0;
|
||||
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
result = TXT_WidgetKeyPress(scrollpane->child, key);
|
||||
|
||||
// Gross hack - if we're scrolling in a menu with the keyboard,
|
||||
// automatically move the scroll pane to show the new
|
||||
// selected item.
|
||||
|
||||
if ((key == KEY_UPARROW || key == KEY_DOWNARROW
|
||||
|| key == KEY_LEFTARROW || key == KEY_RIGHTARROW
|
||||
|| key == KEY_PGUP || key == KEY_PGDN
|
||||
|| key == KEY_TAB)
|
||||
&& scrollpane->child->widget_class == &txt_table_class)
|
||||
{
|
||||
if (PageSelectedWidget(scrollpane, key))
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
|
||||
ShowSelectedWidget(scrollpane);
|
||||
}
|
||||
|
||||
// If the child widget didn't use the keypress, we can see
|
||||
// if it can be interpreted as a scrolling command.
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
result = InterpretScrollKey(scrollpane, key);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void TXT_ScrollPaneMousePress(TXT_UNCAST_ARG(scrollpane),
|
||||
int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_scrollpane_t, scrollpane);
|
||||
int scrollbars;
|
||||
int rel_x, rel_y;
|
||||
|
||||
scrollbars = NeedsScrollbars(scrollpane);
|
||||
|
||||
if (b == TXT_MOUSE_SCROLLUP)
|
||||
{
|
||||
if (scrollbars & SCROLLBAR_VERTICAL)
|
||||
{
|
||||
scrollpane->y -= 3;
|
||||
}
|
||||
else if (scrollbars & SCROLLBAR_HORIZONTAL)
|
||||
{
|
||||
scrollpane->x -= 3;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (b == TXT_MOUSE_SCROLLDOWN)
|
||||
{
|
||||
if (scrollbars & SCROLLBAR_VERTICAL)
|
||||
{
|
||||
scrollpane->y += 3;
|
||||
}
|
||||
else if (scrollbars & SCROLLBAR_HORIZONTAL)
|
||||
{
|
||||
scrollpane->x += 3;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rel_x = x - scrollpane->widget.x;
|
||||
rel_y = y - scrollpane->widget.y;
|
||||
|
||||
// Click on the horizontal scrollbar?
|
||||
if ((scrollbars & SCROLLBAR_HORIZONTAL) && rel_y == scrollpane->h)
|
||||
{
|
||||
if (rel_x == 0)
|
||||
{
|
||||
--scrollpane->x;
|
||||
}
|
||||
else if (rel_x == scrollpane->w - 1)
|
||||
{
|
||||
++scrollpane->x;
|
||||
}
|
||||
else
|
||||
{
|
||||
int range = FullWidth(scrollpane) - scrollpane->w;
|
||||
int bar_max = scrollpane->w - 3;
|
||||
|
||||
scrollpane->x = ((rel_x - 1) * range + bar_max - 1) / bar_max;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Click on the vertical scrollbar?
|
||||
if ((scrollbars & SCROLLBAR_VERTICAL) && rel_x == scrollpane->w)
|
||||
{
|
||||
if (rel_y == 0)
|
||||
{
|
||||
--scrollpane->y;
|
||||
}
|
||||
else if (rel_y == scrollpane->h - 1)
|
||||
{
|
||||
++scrollpane->y;
|
||||
}
|
||||
else
|
||||
{
|
||||
int range = FullHeight(scrollpane) - scrollpane->h;
|
||||
int bar_max = scrollpane->h - 3;
|
||||
|
||||
scrollpane->y = ((rel_y - 1) * range + bar_max - 1) / bar_max;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
TXT_WidgetMousePress(scrollpane->child, x, y, b);
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_ScrollPaneLayout(TXT_UNCAST_ARG(scrollpane))
|
||||
{
|
||||
TXT_CAST_ARG(txt_scrollpane_t, scrollpane);
|
||||
|
||||
SanityCheckScrollbars(scrollpane);
|
||||
|
||||
// The child widget takes the same position as the scroll pane
|
||||
// itself, but is offset by the scroll position.
|
||||
|
||||
if (scrollpane->child != NULL)
|
||||
{
|
||||
scrollpane->child->x = scrollpane->widget.x - scrollpane->x;
|
||||
scrollpane->child->y = scrollpane->widget.y - scrollpane->y;
|
||||
|
||||
TXT_LayoutWidget(scrollpane->child);
|
||||
}
|
||||
}
|
||||
|
||||
static int TXT_ScrollPaneSelectable(TXT_UNCAST_ARG(scrollpane))
|
||||
{
|
||||
TXT_CAST_ARG(txt_scrollpane_t, scrollpane);
|
||||
|
||||
// If scroll bars are displayed, the scroll pane must be selectable
|
||||
// so that we can use the arrow keys to scroll around.
|
||||
|
||||
if (NeedsScrollbars(scrollpane))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Otherwise, whether this is selectable depends on the child widget.
|
||||
|
||||
return TXT_SelectableWidget(scrollpane->child);
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_scrollpane_class =
|
||||
{
|
||||
TXT_ScrollPaneSelectable,
|
||||
TXT_ScrollPaneSizeCalc,
|
||||
TXT_ScrollPaneDrawer,
|
||||
TXT_ScrollPaneKeyPress,
|
||||
TXT_ScrollPaneDestructor,
|
||||
TXT_ScrollPaneMousePress,
|
||||
TXT_ScrollPaneLayout,
|
||||
TXT_ScrollPaneFocused,
|
||||
};
|
||||
|
||||
txt_scrollpane_t *TXT_NewScrollPane(int w, int h, TXT_UNCAST_ARG(target))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, target);
|
||||
txt_scrollpane_t *scrollpane;
|
||||
|
||||
scrollpane = malloc(sizeof(txt_scrollpane_t));
|
||||
TXT_InitWidget(scrollpane, &txt_scrollpane_class);
|
||||
scrollpane->w = w;
|
||||
scrollpane->h = h;
|
||||
scrollpane->x = 0;
|
||||
scrollpane->y = 0;
|
||||
scrollpane->child = target;
|
||||
scrollpane->expand_w = w <= 0;
|
||||
scrollpane->expand_h = h <= 0;
|
||||
|
||||
// Set parent pointer for inner widget.
|
||||
|
||||
target->parent = &scrollpane->widget;
|
||||
|
||||
return scrollpane;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_SCROLLPANE_H
|
||||
#define TXT_SCROLLPANE_H
|
||||
|
||||
/**
|
||||
* @file txt_scrollpane.h
|
||||
*
|
||||
* Scrollable pane widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Scrollable pane widget.
|
||||
*
|
||||
* A scrollable pane widget is a widget that contains another widget
|
||||
* that is larger than it. Scroll bars appear on the side to allow
|
||||
* different areas of the contained widget to be seen.
|
||||
*/
|
||||
|
||||
typedef struct txt_scrollpane_s txt_scrollpane_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_scrollpane_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
int w, h;
|
||||
int x, y;
|
||||
int expand_w, expand_h;
|
||||
txt_widget_t *child;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new scroll pane widget.
|
||||
*
|
||||
* @param w Width of the scroll pane, in characters.
|
||||
* @param h Height of the scroll pane, in lines.
|
||||
* @param target The target widget that the scroll pane will
|
||||
* contain.
|
||||
* @return Pointer to the new scroll pane widget.
|
||||
*/
|
||||
|
||||
txt_scrollpane_t *TXT_NewScrollPane(int w, int h, TXT_UNCAST_ARG(target));
|
||||
|
||||
#endif /* #ifndef TXT_SCROLLPANE_H */
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Text mode emulation in SDL
|
||||
//
|
||||
|
||||
#ifndef TXT_SDL_H
|
||||
#define TXT_SDL_H
|
||||
|
||||
// The textscreen API itself doesn't need SDL; however, SDL needs its
|
||||
// headers included where main() is defined.
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
// Event callback function type: a function of this type can be used
|
||||
// to intercept events in the textscreen event processing loop.
|
||||
// Returning 1 will cause the event to be eaten; the textscreen code
|
||||
// will not see it.
|
||||
|
||||
typedef int (*TxtSDLEventCallbackFunc)(SDL_Event *event, void *user_data);
|
||||
|
||||
// Set a callback function to call in the SDL event loop. Useful for
|
||||
// intercepting events. Pass callback=NULL to clear an existing
|
||||
// callback function.
|
||||
// user_data is a void pointer to be passed to the callback function.
|
||||
|
||||
void TXT_SDL_SetEventCallback(TxtSDLEventCallbackFunc callback, void *user_data);
|
||||
|
||||
#endif /* #ifndef TXT_SDL_H */
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "txt_separator.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
static void TXT_SeparatorSizeCalc(TXT_UNCAST_ARG(separator))
|
||||
{
|
||||
TXT_CAST_ARG(txt_separator_t, separator);
|
||||
|
||||
if (separator->label != NULL)
|
||||
{
|
||||
// Minimum width is the string length + two spaces for padding
|
||||
|
||||
separator->widget.w = TXT_UTF8_Strlen(separator->label) + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
separator->widget.w = 0;
|
||||
}
|
||||
|
||||
separator->widget.h = 1;
|
||||
}
|
||||
|
||||
static void TXT_SeparatorDrawer(TXT_UNCAST_ARG(separator))
|
||||
{
|
||||
TXT_CAST_ARG(txt_separator_t, separator);
|
||||
int x, y;
|
||||
int w;
|
||||
|
||||
w = separator->widget.w;
|
||||
|
||||
TXT_GetXY(&x, &y);
|
||||
|
||||
// Draw special separator with custom hight, width and color argument else draw standard separator
|
||||
// Draw separator. Go back one character and draw two extra
|
||||
// to overlap the window borders.
|
||||
|
||||
if (separator->specialsep == 1)
|
||||
TXT_DrawSpecialSeparator(x, y, w + separator->w, separator->h, separator->sepcolor, 1);
|
||||
else
|
||||
TXT_DrawSeparator(x - 2, y, w + 4, 0, 0);
|
||||
|
||||
if (separator->label != NULL)
|
||||
{
|
||||
if (separator->specialsep == 1)
|
||||
{
|
||||
TXT_GotoXY(x + 1, y);
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_GREEN);
|
||||
|
||||
TXT_DrawString(separator->label);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_GotoXY(x, y);
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_GREEN);
|
||||
|
||||
TXT_DrawString(" ");
|
||||
TXT_DrawString(separator->label);
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_SeparatorDestructor(TXT_UNCAST_ARG(separator))
|
||||
{
|
||||
TXT_CAST_ARG(txt_separator_t, separator);
|
||||
|
||||
free(separator->label);
|
||||
}
|
||||
|
||||
void TXT_SetSeparatorLabel(txt_separator_t *separator, const char *label)
|
||||
{
|
||||
free(separator->label);
|
||||
|
||||
if (label != NULL)
|
||||
{
|
||||
separator->label = strdup(label);
|
||||
}
|
||||
else
|
||||
{
|
||||
separator->label = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_separator_class =
|
||||
{
|
||||
TXT_NeverSelectable,
|
||||
TXT_SeparatorSizeCalc,
|
||||
TXT_SeparatorDrawer,
|
||||
NULL,
|
||||
TXT_SeparatorDestructor,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
txt_separator_t* TXT_NewSpecialSeparator(const char* label, int w, int h, int sepcolor)
|
||||
{
|
||||
txt_separator_t* separator;
|
||||
|
||||
separator = malloc(sizeof(txt_separator_t));
|
||||
|
||||
separator->sepcolor = sepcolor;
|
||||
separator->specialsep = 1;
|
||||
separator->w = w;
|
||||
separator->h = h;
|
||||
|
||||
TXT_InitWidget(separator, &txt_separator_class);
|
||||
|
||||
separator->label = NULL;
|
||||
TXT_SetSeparatorLabel(separator, label);
|
||||
|
||||
return separator;
|
||||
}
|
||||
|
||||
txt_separator_t *TXT_NewSeparator(const char *label)
|
||||
{
|
||||
txt_separator_t *separator;
|
||||
|
||||
separator = malloc(sizeof(txt_separator_t));
|
||||
|
||||
separator->specialsep = 0;
|
||||
|
||||
TXT_InitWidget(separator, &txt_separator_class);
|
||||
|
||||
separator->label = NULL;
|
||||
TXT_SetSeparatorLabel(separator, label);
|
||||
|
||||
return separator;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_SEPARATOR_H
|
||||
#define TXT_SEPARATOR_H
|
||||
|
||||
/**
|
||||
* @file txt_separator.h
|
||||
*
|
||||
* Horizontal separator widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Horizontal separator.
|
||||
*
|
||||
* A horizontal separator appears as a horizontal line divider across
|
||||
* the length of the window in which it is added. An optional label
|
||||
* allows the separator to be used as a section divider for grouping
|
||||
* related controls.
|
||||
*/
|
||||
|
||||
typedef struct txt_separator_s txt_separator_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_separator_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
char *label;
|
||||
int specialsep;
|
||||
int sepcolor;
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
extern txt_widget_class_t txt_separator_class;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new horizontal and vertical separator widget.
|
||||
*
|
||||
* @param label Label to display on the separator (UTF-8 format).
|
||||
* If this is set to NULL, no label is displayed.
|
||||
* @param w Width of separator
|
||||
* @param h Hidth of separator
|
||||
* @param sepcolor Color of separator
|
||||
* @return The new separator widget.
|
||||
*/
|
||||
|
||||
txt_separator_t* TXT_NewSpecialSeparator(const char* label, int w, int h, int sepcolor);
|
||||
|
||||
/**
|
||||
* Create a new horizontal separator widget.
|
||||
*
|
||||
* @param label Label to display on the separator (UTF-8 format).
|
||||
* If this is set to NULL, no label is displayed.
|
||||
* @return The new separator widget.
|
||||
*/
|
||||
|
||||
txt_separator_t *TXT_NewSeparator(const char *label);
|
||||
|
||||
/**
|
||||
* Change the label on a separator.
|
||||
*
|
||||
* @param separator The separator.
|
||||
* @param label The new label (UTF-8 format).
|
||||
*/
|
||||
|
||||
void TXT_SetSeparatorLabel(txt_separator_t *separator, const char *label);
|
||||
|
||||
#endif /* #ifndef TXT_SEPARATOR_H */
|
||||
|
||||
@@ -0,0 +1,424 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_spinctrl.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
// Generate the format string to be used for displaying floats
|
||||
|
||||
static void FloatFormatString(float step, char *buf, size_t buf_len)
|
||||
{
|
||||
int precision;
|
||||
|
||||
precision = (int) ceil(-log(step) / log(10));
|
||||
|
||||
if (precision > 0)
|
||||
{
|
||||
TXT_snprintf(buf, buf_len, "%%.%if", precision);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_StringCopy(buf, "%.1f", buf_len);
|
||||
}
|
||||
}
|
||||
|
||||
// Number of characters needed to represent a character
|
||||
|
||||
static unsigned int IntWidth(int val)
|
||||
{
|
||||
char buf[25];
|
||||
|
||||
TXT_snprintf(buf, sizeof(buf), "%i", val);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static unsigned int FloatWidth(float val, float step)
|
||||
{
|
||||
unsigned int precision;
|
||||
unsigned int result;
|
||||
|
||||
// Calculate the width of the int value
|
||||
|
||||
result = IntWidth((int) val);
|
||||
|
||||
// Add a decimal part if the precision specifies it
|
||||
|
||||
precision = (unsigned int) ceil(-log(step) / log(10));
|
||||
|
||||
if (precision > 0)
|
||||
{
|
||||
result += precision + 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the minimum width of the input box
|
||||
|
||||
static unsigned int SpinControlWidth(txt_spincontrol_t *spincontrol)
|
||||
{
|
||||
unsigned int minw, maxw;
|
||||
|
||||
switch (spincontrol->type)
|
||||
{
|
||||
case TXT_SPINCONTROL_FLOAT:
|
||||
minw = FloatWidth(spincontrol->min.f, spincontrol->step.f);
|
||||
maxw = FloatWidth(spincontrol->max.f, spincontrol->step.f);
|
||||
break;
|
||||
|
||||
default:
|
||||
case TXT_SPINCONTROL_INT:
|
||||
minw = IntWidth(spincontrol->min.i);
|
||||
maxw = IntWidth(spincontrol->max.i);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Choose the wider of the two values. Add one so that there is always
|
||||
// space for the cursor when editing.
|
||||
|
||||
if (minw > maxw)
|
||||
{
|
||||
return minw;
|
||||
}
|
||||
else
|
||||
{
|
||||
return maxw;
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_SpinControlSizeCalc(TXT_UNCAST_ARG(spincontrol))
|
||||
{
|
||||
TXT_CAST_ARG(txt_spincontrol_t, spincontrol);
|
||||
|
||||
spincontrol->widget.w = SpinControlWidth(spincontrol) + 5;
|
||||
spincontrol->widget.h = 1;
|
||||
}
|
||||
|
||||
static void SetBuffer(txt_spincontrol_t *spincontrol)
|
||||
{
|
||||
char format[25];
|
||||
|
||||
switch (spincontrol->type)
|
||||
{
|
||||
case TXT_SPINCONTROL_INT:
|
||||
TXT_snprintf(spincontrol->buffer, spincontrol->buffer_len,
|
||||
"%i", spincontrol->value->i);
|
||||
break;
|
||||
|
||||
case TXT_SPINCONTROL_FLOAT:
|
||||
FloatFormatString(spincontrol->step.f, format, sizeof(format));
|
||||
TXT_snprintf(spincontrol->buffer, spincontrol->buffer_len,
|
||||
format, spincontrol->value->f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol))
|
||||
{
|
||||
TXT_CAST_ARG(txt_spincontrol_t, spincontrol);
|
||||
unsigned int i;
|
||||
unsigned int padding;
|
||||
txt_saved_colors_t colors;
|
||||
int bw;
|
||||
int focused;
|
||||
|
||||
focused = spincontrol->widget.focused;
|
||||
|
||||
TXT_SaveColors(&colors);
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
TXT_DrawCodePageString("\x1b ");
|
||||
|
||||
TXT_RestoreColors(&colors);
|
||||
|
||||
// Choose background color
|
||||
|
||||
if (focused && spincontrol->editing)
|
||||
{
|
||||
TXT_BGColor(TXT_COLOR_BLACK, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_SetWidgetBG(spincontrol);
|
||||
}
|
||||
|
||||
if (!spincontrol->editing)
|
||||
{
|
||||
SetBuffer(spincontrol);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
bw = TXT_UTF8_Strlen(spincontrol->buffer);
|
||||
padding = spincontrol->widget.w - bw - 4;
|
||||
|
||||
while (i < padding)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
++i;
|
||||
}
|
||||
|
||||
TXT_DrawString(spincontrol->buffer);
|
||||
i += bw;
|
||||
|
||||
while (i < spincontrol->widget.w - 4)
|
||||
{
|
||||
TXT_DrawString(" ");
|
||||
++i;
|
||||
}
|
||||
|
||||
TXT_RestoreColors(&colors);
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
TXT_DrawCodePageString(" \x1a");
|
||||
}
|
||||
|
||||
static void TXT_SpinControlDestructor(TXT_UNCAST_ARG(spincontrol))
|
||||
{
|
||||
TXT_CAST_ARG(txt_spincontrol_t, spincontrol);
|
||||
|
||||
free(spincontrol->buffer);
|
||||
}
|
||||
|
||||
static void AddCharacter(txt_spincontrol_t *spincontrol, int key)
|
||||
{
|
||||
if (TXT_UTF8_Strlen(spincontrol->buffer) < SpinControlWidth(spincontrol)
|
||||
&& strlen(spincontrol->buffer) < spincontrol->buffer_len - 2)
|
||||
{
|
||||
spincontrol->buffer[strlen(spincontrol->buffer) + 1] = '\0';
|
||||
spincontrol->buffer[strlen(spincontrol->buffer)] = key;
|
||||
}
|
||||
}
|
||||
|
||||
static void Backspace(txt_spincontrol_t *spincontrol)
|
||||
{
|
||||
if (TXT_UTF8_Strlen(spincontrol->buffer) > 0)
|
||||
{
|
||||
spincontrol->buffer[strlen(spincontrol->buffer) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static void EnforceLimits(txt_spincontrol_t *spincontrol)
|
||||
{
|
||||
switch (spincontrol->type)
|
||||
{
|
||||
case TXT_SPINCONTROL_INT:
|
||||
if (spincontrol->value->i > spincontrol->max.i)
|
||||
spincontrol->value->i = spincontrol->max.i;
|
||||
else if (spincontrol->value->i < spincontrol->min.i)
|
||||
spincontrol->value->i = spincontrol->min.i;
|
||||
break;
|
||||
|
||||
case TXT_SPINCONTROL_FLOAT:
|
||||
if (spincontrol->value->f > spincontrol->max.f)
|
||||
spincontrol->value->f = spincontrol->max.f;
|
||||
else if (spincontrol->value->f < spincontrol->min.f)
|
||||
spincontrol->value->f = spincontrol->min.f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FinishEditing(txt_spincontrol_t *spincontrol)
|
||||
{
|
||||
switch (spincontrol->type)
|
||||
{
|
||||
case TXT_SPINCONTROL_INT:
|
||||
spincontrol->value->i = atoi(spincontrol->buffer);
|
||||
break;
|
||||
|
||||
case TXT_SPINCONTROL_FLOAT:
|
||||
spincontrol->value->f = (float) atof(spincontrol->buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
spincontrol->editing = 0;
|
||||
EnforceLimits(spincontrol);
|
||||
}
|
||||
|
||||
static int TXT_SpinControlKeyPress(TXT_UNCAST_ARG(spincontrol), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_spincontrol_t, spincontrol);
|
||||
|
||||
// Enter to enter edit mode
|
||||
|
||||
if (spincontrol->editing)
|
||||
{
|
||||
if (key == KEY_ENTER)
|
||||
{
|
||||
FinishEditing(spincontrol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key == KEY_ESCAPE)
|
||||
{
|
||||
// Abort without saving value
|
||||
spincontrol->editing = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (isdigit(key) || key == '-' || key == '.')
|
||||
{
|
||||
AddCharacter(spincontrol, key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key == KEY_BACKSPACE)
|
||||
{
|
||||
Backspace(spincontrol);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-editing mode
|
||||
|
||||
if (key == KEY_ENTER)
|
||||
{
|
||||
spincontrol->editing = 1;
|
||||
TXT_StringCopy(spincontrol->buffer, "", spincontrol->buffer_len);
|
||||
return 1;
|
||||
}
|
||||
if (key == KEY_LEFTARROW)
|
||||
{
|
||||
switch (spincontrol->type)
|
||||
{
|
||||
case TXT_SPINCONTROL_INT:
|
||||
spincontrol->value->i -= spincontrol->step.i;
|
||||
break;
|
||||
|
||||
case TXT_SPINCONTROL_FLOAT:
|
||||
spincontrol->value->f -= spincontrol->step.f;
|
||||
break;
|
||||
}
|
||||
|
||||
EnforceLimits(spincontrol);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key == KEY_RIGHTARROW)
|
||||
{
|
||||
switch (spincontrol->type)
|
||||
{
|
||||
case TXT_SPINCONTROL_INT:
|
||||
spincontrol->value->i += spincontrol->step.i;
|
||||
break;
|
||||
|
||||
case TXT_SPINCONTROL_FLOAT:
|
||||
spincontrol->value->f += spincontrol->step.f;
|
||||
break;
|
||||
}
|
||||
|
||||
EnforceLimits(spincontrol);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TXT_SpinControlMousePress(TXT_UNCAST_ARG(spincontrol),
|
||||
int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_spincontrol_t, spincontrol);
|
||||
unsigned int rel_x;
|
||||
|
||||
rel_x = x - spincontrol->widget.x;
|
||||
|
||||
if (rel_x < 2)
|
||||
{
|
||||
TXT_SpinControlKeyPress(spincontrol, KEY_LEFTARROW);
|
||||
}
|
||||
else if (rel_x >= spincontrol->widget.w - 2)
|
||||
{
|
||||
TXT_SpinControlKeyPress(spincontrol, KEY_RIGHTARROW);
|
||||
}
|
||||
}
|
||||
|
||||
static void TXT_SpinControlFocused(TXT_UNCAST_ARG(spincontrol), int focused)
|
||||
{
|
||||
TXT_CAST_ARG(txt_spincontrol_t, spincontrol);
|
||||
|
||||
FinishEditing(spincontrol);
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_spincontrol_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_SpinControlSizeCalc,
|
||||
TXT_SpinControlDrawer,
|
||||
TXT_SpinControlKeyPress,
|
||||
TXT_SpinControlDestructor,
|
||||
TXT_SpinControlMousePress,
|
||||
NULL,
|
||||
TXT_SpinControlFocused,
|
||||
};
|
||||
|
||||
static txt_spincontrol_t *TXT_BaseSpinControl(void)
|
||||
{
|
||||
txt_spincontrol_t *spincontrol;
|
||||
|
||||
spincontrol = malloc(sizeof(txt_spincontrol_t));
|
||||
|
||||
TXT_InitWidget(spincontrol, &txt_spincontrol_class);
|
||||
spincontrol->buffer_len = 25;
|
||||
spincontrol->buffer = malloc(spincontrol->buffer_len);
|
||||
TXT_StringCopy(spincontrol->buffer, "", spincontrol->buffer_len);
|
||||
spincontrol->editing = 0;
|
||||
|
||||
return spincontrol;
|
||||
}
|
||||
|
||||
txt_spincontrol_t *TXT_NewSpinControl(int *value, int min, int max)
|
||||
{
|
||||
txt_spincontrol_t *spincontrol;
|
||||
|
||||
spincontrol = TXT_BaseSpinControl();
|
||||
spincontrol->type = TXT_SPINCONTROL_INT;
|
||||
spincontrol->value = (void *) value;
|
||||
spincontrol->min.i = min;
|
||||
spincontrol->max.i = max;
|
||||
spincontrol->step.i = 1;
|
||||
|
||||
return spincontrol;
|
||||
}
|
||||
|
||||
txt_spincontrol_t *TXT_NewFloatSpinControl(float *value, float min, float max)
|
||||
{
|
||||
txt_spincontrol_t *spincontrol;
|
||||
|
||||
spincontrol = TXT_BaseSpinControl();
|
||||
spincontrol->type = TXT_SPINCONTROL_FLOAT;
|
||||
spincontrol->value = (void *) value;
|
||||
spincontrol->min.f = min;
|
||||
spincontrol->max.f = max;
|
||||
spincontrol->step.f = 0.1f;
|
||||
|
||||
return spincontrol;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_SPINCONTROL_H
|
||||
#define TXT_SPINCONTROL_H
|
||||
|
||||
/**
|
||||
* @file txt_spinctrl.h
|
||||
*
|
||||
* Spin control widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spin control widget.
|
||||
*
|
||||
* A spin control widget works as an input box that can be used to
|
||||
* set numeric values, but also has buttons that allow its value
|
||||
* to be increased or decreased.
|
||||
*/
|
||||
|
||||
typedef struct txt_spincontrol_s txt_spincontrol_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TXT_SPINCONTROL_INT,
|
||||
TXT_SPINCONTROL_FLOAT,
|
||||
} txt_spincontrol_type_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_spincontrol_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
txt_spincontrol_type_t type;
|
||||
union { float f; int i; } min, max, *value, step;
|
||||
int editing;
|
||||
char *buffer;
|
||||
size_t buffer_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new spin control widget tracking an integer value.
|
||||
*
|
||||
* @param value Pointer to the variable containing the value
|
||||
* displayed in the widget.
|
||||
* @param min Minimum value that may be set.
|
||||
* @param max Maximum value that may be set.
|
||||
* @return Pointer to the new spin control widget.
|
||||
*/
|
||||
|
||||
txt_spincontrol_t *TXT_NewSpinControl(int *value, int min, int max);
|
||||
|
||||
/**
|
||||
* Create a new spin control widget tracking a float value.
|
||||
*
|
||||
* @param value Pointer to the variable containing the value
|
||||
* displayed in the widget.
|
||||
* @param min Minimum value that may be set.
|
||||
* @param max Maximum value that may be set.
|
||||
* @return Pointer to the new spin control widget.
|
||||
*/
|
||||
|
||||
txt_spincontrol_t *TXT_NewFloatSpinControl(float *value, float min, float max);
|
||||
|
||||
#endif /* #ifndef TXT_SPINCONTROL_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_strut.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
static void TXT_StrutSizeCalc(TXT_UNCAST_ARG(strut))
|
||||
{
|
||||
TXT_CAST_ARG(txt_strut_t, strut);
|
||||
|
||||
// Minimum width is the string length + two spaces for padding
|
||||
|
||||
strut->widget.w = strut->width;
|
||||
strut->widget.h = strut->height;
|
||||
}
|
||||
|
||||
static void TXT_StrutDrawer(TXT_UNCAST_ARG(strut))
|
||||
{
|
||||
// Nothing is drawn for a strut.
|
||||
}
|
||||
|
||||
static void TXT_StrutDestructor(TXT_UNCAST_ARG(strut))
|
||||
{
|
||||
}
|
||||
|
||||
static int TXT_StrutKeyPress(TXT_UNCAST_ARG(strut), int key)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_strut_class =
|
||||
{
|
||||
TXT_NeverSelectable,
|
||||
TXT_StrutSizeCalc,
|
||||
TXT_StrutDrawer,
|
||||
TXT_StrutKeyPress,
|
||||
TXT_StrutDestructor,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
txt_strut_t *TXT_NewStrut(int width, int height)
|
||||
{
|
||||
txt_strut_t *strut;
|
||||
|
||||
strut = malloc(sizeof(txt_strut_t));
|
||||
|
||||
TXT_InitWidget(strut, &txt_strut_class);
|
||||
strut->width = width;
|
||||
strut->height = height;
|
||||
|
||||
return strut;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_STRUT_H
|
||||
#define TXT_STRUT_H
|
||||
|
||||
/**
|
||||
* @file txt_strut.h
|
||||
*
|
||||
* Strut widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Strut widget.
|
||||
*
|
||||
* A strut is a widget that takes up a fixed amount of space. It can
|
||||
* be visualised as a transparent box. Struts are used to provide
|
||||
* spacing between widgets.
|
||||
*/
|
||||
|
||||
typedef struct txt_strut_s txt_strut_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_strut_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new strut.
|
||||
*
|
||||
* @param width Width of the strut, in characters.
|
||||
* @param height Height of the strut, in characters.
|
||||
*/
|
||||
|
||||
txt_strut_t *TXT_NewStrut(int width, int height);
|
||||
|
||||
#endif /* #ifndef TXT_STRUT_H */
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,245 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_TABLE_H
|
||||
#define TXT_TABLE_H
|
||||
|
||||
/**
|
||||
* @file txt_table.h
|
||||
*
|
||||
* Table widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Magic value that if used in a table, will indicate that the cell is
|
||||
* empty and the widget in the cell to the left can overflow into it.
|
||||
*/
|
||||
|
||||
#define TXT_TABLE_OVERFLOW_RIGHT (&txt_table_overflow_right)
|
||||
|
||||
/**
|
||||
* Magic value that if used in a table, will indicate that the cell is
|
||||
* empty and the widget in the cell above it can overflow down into it.
|
||||
*/
|
||||
|
||||
#define TXT_TABLE_OVERFLOW_DOWN (&txt_table_overflow_down)
|
||||
|
||||
/**
|
||||
* Magic value that if given to @ref TXT_AddWidget(), will pad out all
|
||||
* columns until the end of line.
|
||||
*/
|
||||
#define TXT_TABLE_EOL (&txt_table_eol)
|
||||
|
||||
/**
|
||||
* Indicates an empty space to @ref TXT_AddWidgets(). Equivalent to
|
||||
* TXT_AddWidget(table, NULL), except that NULL is used by TXT_AddWidgets()
|
||||
* to indicate the end of input.
|
||||
*/
|
||||
#define TXT_TABLE_EMPTY (&txt_table_empty)
|
||||
|
||||
/**
|
||||
* Table widget.
|
||||
*
|
||||
* A table is a widget that contains other widgets. It may have
|
||||
* multiple columns, in which case the child widgets are laid out
|
||||
* in a grid. Columns automatically grow as necessary, although
|
||||
* minimum column widths can be set using @ref TXT_SetColumnWidths.
|
||||
*
|
||||
* To create a new table, use @ref TXT_NewTable. It is also
|
||||
* possible to use @ref TXT_NewHorizBox to create a table, specifying
|
||||
* widgets to place inside a horizontal list. A vertical list is
|
||||
* possible simply by creating a table containing a single column.
|
||||
*/
|
||||
|
||||
typedef struct txt_table_s txt_table_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_table_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
|
||||
// Widgets in this table
|
||||
// The widget at (x,y) in the table is widgets[columns * y + x]
|
||||
txt_widget_t **widgets;
|
||||
int num_widgets;
|
||||
|
||||
// Number of columns
|
||||
int columns;
|
||||
|
||||
// Currently selected:
|
||||
int selected_x;
|
||||
int selected_y;
|
||||
};
|
||||
|
||||
extern txt_widget_class_t txt_table_class;
|
||||
extern txt_widget_t txt_table_overflow_right;
|
||||
extern txt_widget_t txt_table_overflow_down;
|
||||
extern txt_widget_t txt_table_eol;
|
||||
extern txt_widget_t txt_table_empty;
|
||||
|
||||
void TXT_InitTable(txt_table_t *table, int columns);
|
||||
|
||||
/**
|
||||
* Create a new table.
|
||||
*
|
||||
* @param columns The number of columns in the new table.
|
||||
* @return Pointer to the new table structure.
|
||||
*/
|
||||
|
||||
txt_table_t *TXT_NewTable(int columns);
|
||||
|
||||
/**
|
||||
* Create a new table and populate it with provided widgets.
|
||||
*
|
||||
* The arguments to this function are variable. Each argument must be a
|
||||
* pointer to a widget, and the list is terminated with a NULL.
|
||||
*
|
||||
* @param columns The number of columns in the new table.
|
||||
* @return Pointer to the new table structure.
|
||||
*/
|
||||
|
||||
txt_table_t *TXT_MakeTable(int columns, ...);
|
||||
|
||||
/**
|
||||
* Create a table containing the specified widgets packed horizontally,
|
||||
* from left to right.
|
||||
*
|
||||
* The arguments to this function are variable. Each argument must
|
||||
* be a pointer to a widget, and the list is terminated with a
|
||||
* NULL.
|
||||
*
|
||||
* @return Pointer to the new table structure.
|
||||
*/
|
||||
|
||||
txt_table_t *TXT_NewHorizBox(TXT_UNCAST_ARG(first_widget), ...);
|
||||
|
||||
/**
|
||||
* Get the currently selected widget within a table.
|
||||
*
|
||||
* This function will recurse through subtables if necessary.
|
||||
*
|
||||
* @param table The table.
|
||||
* @return Pointer to the widget that is currently selected.
|
||||
*/
|
||||
|
||||
txt_widget_t *TXT_GetSelectedWidget(TXT_UNCAST_ARG(table));
|
||||
|
||||
/**
|
||||
* Add a widget to a table.
|
||||
*
|
||||
* Widgets are added to tables horizontally, from left to right.
|
||||
* For example, for a table with three columns, the first call
|
||||
* to this function will add a widget to the first column, the second
|
||||
* call to the second column, the third call to the third column,
|
||||
* and the fourth will return to the first column, starting a new
|
||||
* row.
|
||||
*
|
||||
* For adding many widgets, it may be easier to use
|
||||
* @ref TXT_AddWidgets.
|
||||
*
|
||||
* @param table The table.
|
||||
* @param widget The widget to add.
|
||||
*/
|
||||
|
||||
void TXT_AddWidget(TXT_UNCAST_ARG(table), TXT_UNCAST_ARG(widget));
|
||||
|
||||
/**
|
||||
* Add multiple widgets to a table.
|
||||
*
|
||||
* Widgets are added as described in the documentation for the
|
||||
* @ref TXT_AddWidget function. This function adds multiple
|
||||
* widgets. The number of arguments is variable, and the argument
|
||||
* list must be terminated by a NULL pointer.
|
||||
*
|
||||
* @param table The table.
|
||||
*/
|
||||
|
||||
void TXT_AddWidgets(TXT_UNCAST_ARG(table), ...);
|
||||
|
||||
/**
|
||||
* Select the given widget that is contained within the specified
|
||||
* table.
|
||||
*
|
||||
* This function will recursively search through subtables if
|
||||
* necessary.
|
||||
*
|
||||
* @param table The table.
|
||||
* @param widget The widget to select.
|
||||
* @return Non-zero (true) if it has been selected,
|
||||
* or zero (false) if it was not found within
|
||||
* this table.
|
||||
*/
|
||||
|
||||
int TXT_SelectWidget(TXT_UNCAST_ARG(table), TXT_UNCAST_ARG(widget));
|
||||
|
||||
/**
|
||||
* Change the number of columns in the table.
|
||||
*
|
||||
* Existing widgets in the table will be preserved, unless the change
|
||||
* reduces the number of columns, in which case the widgets from the
|
||||
* 'deleted' columns will be freed.
|
||||
*
|
||||
* This function can be useful for changing the number of columns in
|
||||
* a window, which by default are tables containing a single column.
|
||||
*
|
||||
* @param table The table.
|
||||
* @param new_columns The new number of columns.
|
||||
*/
|
||||
|
||||
void TXT_SetTableColumns(TXT_UNCAST_ARG(table), int new_columns);
|
||||
|
||||
/**
|
||||
* Set the widths of the columns of the table.
|
||||
*
|
||||
* The arguments to this function are variable, and correspond
|
||||
* to the number of columns in the table. For example, if a table
|
||||
* has five columns, the width of each of the five columns must be
|
||||
* specified.
|
||||
*
|
||||
* The width values are in number of characters.
|
||||
*
|
||||
* Note that this function only sets the minimum widths for columns;
|
||||
* if the columns contain widgets that are wider than the widths
|
||||
* specified, they will be larger.
|
||||
*
|
||||
* @param table The table.
|
||||
*/
|
||||
|
||||
void TXT_SetColumnWidths(TXT_UNCAST_ARG(table), ...);
|
||||
|
||||
/**
|
||||
* Remove all widgets from a table.
|
||||
*
|
||||
* @param table The table.
|
||||
*/
|
||||
|
||||
void TXT_ClearTable(TXT_UNCAST_ARG(table));
|
||||
|
||||
/**
|
||||
* Hack to move the selection in a table by a 'page', triggered by the
|
||||
* scrollpane. This acts as per the keyboard events for the arrows, but moves
|
||||
* the selection by at least the specified number of characters.
|
||||
*
|
||||
* @param table The table.
|
||||
* @param pagex Minimum distance to move the selection horizontally.
|
||||
* @param pagey Minimum distance to move the selection vertically.
|
||||
* @return Non-zero if the selection has been changed.
|
||||
*/
|
||||
|
||||
int TXT_PageTable(TXT_UNCAST_ARG(table), int pagex, int pagey);
|
||||
|
||||
#endif /* #ifndef TXT_TABLE_T */
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "txt_utf8.h"
|
||||
|
||||
// Encode a Unicode character as UTF-8, storing it in the buffer 'p'
|
||||
// and returning the new, incremented position.
|
||||
|
||||
char *TXT_EncodeUTF8(char *p, unsigned int c)
|
||||
{
|
||||
if (c < 0x80) // 1 character (ASCII):
|
||||
{
|
||||
p[0] = c;
|
||||
return p + 1;
|
||||
}
|
||||
else if (c < 0x800) // 2 character:
|
||||
{
|
||||
p[0] = 0xc0 | (c >> 6);
|
||||
p[1] = 0x80 | (c & 0x3f);
|
||||
return p + 2;
|
||||
}
|
||||
else if (c < 0x10000) // 3 chacater:
|
||||
{
|
||||
p[0] = 0xe0 | (c >> 12);
|
||||
p[1] = 0x80 | ((c >> 6) & 0x3f);
|
||||
p[2] = 0x80 | (c & 0x3f);
|
||||
return p + 3;
|
||||
}
|
||||
else if (c < 0x200000) // 4 character:
|
||||
{
|
||||
p[0] = 0xf0 | (c >> 18);
|
||||
p[1] = 0x80 | ((c >> 12) & 0x3f);
|
||||
p[2] = 0x80 | ((c >> 6) & 0x3f);
|
||||
p[3] = 0x80 | (c & 0x3f);
|
||||
return p + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Too big!
|
||||
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
// Decode UTF-8 character, incrementing *ptr over the decoded bytes.
|
||||
|
||||
unsigned int TXT_DecodeUTF8(const char **ptr)
|
||||
{
|
||||
const char *p = *ptr;
|
||||
unsigned int c;
|
||||
|
||||
// UTF-8 decode.
|
||||
|
||||
if ((*p & 0x80) == 0) // 1 character (ASCII):
|
||||
{
|
||||
c = *p;
|
||||
*ptr += 1;
|
||||
}
|
||||
else if ((p[0] & 0xe0) == 0xc0 // 2 character:
|
||||
&& (p[1] & 0xc0) == 0x80)
|
||||
{
|
||||
c = ((p[0] & 0x1f) << 6)
|
||||
| (p[1] & 0x3f);
|
||||
*ptr += 2;
|
||||
}
|
||||
else if ((p[0] & 0xf0) == 0xe0 // 3 character:
|
||||
&& (p[1] & 0xc0) == 0x80
|
||||
&& (p[2] & 0xc0) == 0x80)
|
||||
{
|
||||
c = ((p[0] & 0x0f) << 12)
|
||||
| ((p[1] & 0x3f) << 6)
|
||||
| (p[2] & 0x3f);
|
||||
*ptr += 3;
|
||||
}
|
||||
else if ((p[0] & 0xf8) == 0xf0 // 4 character:
|
||||
&& (p[1] & 0xc0) == 0x80
|
||||
&& (p[2] & 0xc0) == 0x80
|
||||
&& (p[3] & 0xc0) == 0x80)
|
||||
{
|
||||
c = ((p[0] & 0x07) << 18)
|
||||
| ((p[1] & 0x3f) << 12)
|
||||
| ((p[2] & 0x3f) << 6)
|
||||
| (p[3] & 0x3f);
|
||||
*ptr += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decode failure.
|
||||
// Don't bother with 5/6 byte sequences.
|
||||
|
||||
c = 0;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
// Count the number of characters in a UTF-8 string.
|
||||
|
||||
unsigned int TXT_UTF8_Strlen(const char *s)
|
||||
{
|
||||
const char *p;
|
||||
unsigned int result = 0;
|
||||
unsigned int c;
|
||||
|
||||
for (p = s; *p != '\0';)
|
||||
{
|
||||
c = TXT_DecodeUTF8(&p);
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Skip past the first n characters in a UTF-8 string.
|
||||
|
||||
char *TXT_UTF8_SkipChars(const char *s, unsigned int n)
|
||||
{
|
||||
unsigned int i;
|
||||
const char *p;
|
||||
|
||||
p = s;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
if (TXT_DecodeUTF8(&p) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (char *) p;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_UTF8_H
|
||||
#define TXT_UTF8_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
char *TXT_EncodeUTF8(char *p, unsigned int c);
|
||||
unsigned int TXT_DecodeUTF8(const char **ptr);
|
||||
unsigned int TXT_UTF8_Strlen(const char *s);
|
||||
char *TXT_UTF8_SkipChars(const char *s, unsigned int n);
|
||||
|
||||
#endif /* #ifndef TXT_UTF8_H */
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "txt_io.h"
|
||||
#include "txt_widget.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_desktop.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *signal_name;
|
||||
TxtWidgetSignalFunc func;
|
||||
void *user_data;
|
||||
} txt_callback_t;
|
||||
|
||||
struct txt_callback_table_s
|
||||
{
|
||||
int refcount;
|
||||
txt_callback_t *callbacks;
|
||||
int num_callbacks;
|
||||
};
|
||||
|
||||
txt_callback_table_t *TXT_NewCallbackTable(void)
|
||||
{
|
||||
txt_callback_table_t *table;
|
||||
|
||||
table = malloc(sizeof(txt_callback_table_t));
|
||||
table->callbacks = NULL;
|
||||
table->num_callbacks = 0;
|
||||
table->refcount = 1;
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void TXT_RefCallbackTable(txt_callback_table_t *table)
|
||||
{
|
||||
++table->refcount;
|
||||
}
|
||||
|
||||
void TXT_UnrefCallbackTable(txt_callback_table_t *table)
|
||||
{
|
||||
int i;
|
||||
|
||||
--table->refcount;
|
||||
|
||||
if (table->refcount == 0)
|
||||
{
|
||||
// No more references to this table
|
||||
|
||||
for (i=0; i<table->num_callbacks; ++i)
|
||||
{
|
||||
free(table->callbacks[i].signal_name);
|
||||
}
|
||||
|
||||
free(table->callbacks);
|
||||
free(table);
|
||||
}
|
||||
}
|
||||
|
||||
void TXT_InitWidget(TXT_UNCAST_ARG(widget), txt_widget_class_t *widget_class)
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
widget->widget_class = widget_class;
|
||||
widget->callback_table = TXT_NewCallbackTable();
|
||||
widget->parent = NULL;
|
||||
|
||||
// Not focused until we hear otherwise.
|
||||
|
||||
widget->focused = 0;
|
||||
|
||||
// Visible by default.
|
||||
|
||||
widget->visible = 1;
|
||||
|
||||
// Align left by default
|
||||
|
||||
widget->align = TXT_HORIZ_LEFT;
|
||||
|
||||
// No helplabel by default
|
||||
|
||||
widget->is_helplabel_set = 0;
|
||||
}
|
||||
|
||||
void TXT_SignalConnect(TXT_UNCAST_ARG(widget),
|
||||
const char *signal_name,
|
||||
TxtWidgetSignalFunc func,
|
||||
void *user_data)
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
txt_callback_table_t *table;
|
||||
txt_callback_t *callback;
|
||||
|
||||
table = widget->callback_table;
|
||||
|
||||
// Add a new callback to the table
|
||||
|
||||
table->callbacks
|
||||
= realloc(table->callbacks,
|
||||
sizeof(txt_callback_t) * (table->num_callbacks + 1));
|
||||
callback = &table->callbacks[table->num_callbacks];
|
||||
++table->num_callbacks;
|
||||
|
||||
callback->signal_name = strdup(signal_name);
|
||||
callback->func = func;
|
||||
callback->user_data = user_data;
|
||||
}
|
||||
|
||||
void TXT_EmitSignal(TXT_UNCAST_ARG(widget), const char *signal_name)
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
txt_callback_table_t *table;
|
||||
int i;
|
||||
|
||||
table = widget->callback_table;
|
||||
|
||||
// Don't destroy the table while we're searching through it
|
||||
// (one of the callbacks may destroy this window)
|
||||
|
||||
TXT_RefCallbackTable(table);
|
||||
|
||||
// Search the table for all callbacks with this name and invoke
|
||||
// the functions.
|
||||
|
||||
for (i=0; i<table->num_callbacks; ++i)
|
||||
{
|
||||
if (!strcmp(table->callbacks[i].signal_name, signal_name))
|
||||
{
|
||||
table->callbacks[i].func(widget, table->callbacks[i].user_data);
|
||||
}
|
||||
}
|
||||
|
||||
// Finished using the table
|
||||
|
||||
TXT_UnrefCallbackTable(table);
|
||||
}
|
||||
|
||||
void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
widget->widget_class->size_calc(widget);
|
||||
}
|
||||
|
||||
void TXT_DrawWidget(TXT_UNCAST_ARG(widget))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
txt_saved_colors_t colors;
|
||||
|
||||
// The drawing function might change the fg/bg colors,
|
||||
// so make sure we restore them after it's done.
|
||||
|
||||
TXT_SaveColors(&colors);
|
||||
|
||||
// For convenience...
|
||||
|
||||
TXT_GotoXY(widget->x, widget->y);
|
||||
|
||||
// Call drawer method
|
||||
|
||||
widget->widget_class->drawer(widget);
|
||||
|
||||
TXT_RestoreColors(&colors);
|
||||
}
|
||||
|
||||
void TXT_DestroyWidget(TXT_UNCAST_ARG(widget))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
widget->widget_class->destructor(widget);
|
||||
TXT_UnrefCallbackTable(widget->callback_table);
|
||||
free(widget);
|
||||
}
|
||||
|
||||
int TXT_WidgetKeyPress(TXT_UNCAST_ARG(widget), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
if (widget->widget_class->key_press != NULL)
|
||||
{
|
||||
return widget->widget_class->key_press(widget, key);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TXT_SetWidgetFocus(TXT_UNCAST_ARG(widget), int focused)
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
if (widget == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget->focused != focused)
|
||||
{
|
||||
widget->focused = focused;
|
||||
|
||||
if (widget->widget_class->focus_change != NULL)
|
||||
{
|
||||
widget->widget_class->focus_change(widget, focused);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TXT_SetWidgetAlign(TXT_UNCAST_ARG(widget), txt_horiz_align_t horiz_align)
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
widget->align = horiz_align;
|
||||
}
|
||||
|
||||
void TXT_WidgetMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
if (widget->widget_class->mouse_press != NULL)
|
||||
{
|
||||
widget->widget_class->mouse_press(widget, x, y, b);
|
||||
}
|
||||
}
|
||||
|
||||
void TXT_LayoutWidget(TXT_UNCAST_ARG(widget))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
if (widget->widget_class->layout != NULL)
|
||||
{
|
||||
widget->widget_class->layout(widget);
|
||||
}
|
||||
}
|
||||
|
||||
int TXT_AlwaysSelectable(TXT_UNCAST_ARG(widget))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TXT_NeverSelectable(TXT_UNCAST_ARG(widget))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TXT_SelectableWidget(TXT_UNCAST_ARG(widget))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
if (widget->widget_class->selectable != NULL)
|
||||
{
|
||||
return widget->widget_class->selectable(widget);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int TXT_ContainsWidget(TXT_UNCAST_ARG(haystack), TXT_UNCAST_ARG(needle))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, haystack);
|
||||
TXT_CAST_ARG(txt_widget_t, needle);
|
||||
|
||||
while (needle != NULL)
|
||||
{
|
||||
if (needle == haystack)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
needle = needle->parent;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TXT_HoveringOverWidget(TXT_UNCAST_ARG(widget))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
txt_window_t *active_window;
|
||||
int x, y;
|
||||
|
||||
// We can only be hovering over widgets in the active window.
|
||||
|
||||
active_window = TXT_GetActiveWindow();
|
||||
|
||||
if (active_window == NULL || !TXT_ContainsWidget(active_window, widget))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is the mouse cursor within the bounds of the widget?
|
||||
|
||||
TXT_GetMousePosition(&x, &y);
|
||||
|
||||
return (x >= widget->x && x < widget->x + widget->w
|
||||
&& y >= widget->y && y < widget->y + widget->h);
|
||||
}
|
||||
|
||||
void TXT_SetHelpLabel(TXT_UNCAST_ARG(widget), const char* helplabel)
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
|
||||
widget->helplabel = strdup(helplabel);
|
||||
|
||||
widget->is_helplabel_set = 1;
|
||||
}
|
||||
|
||||
void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, widget);
|
||||
txt_window_t* active_window;
|
||||
|
||||
active_window = TXT_GetActiveWindow();
|
||||
|
||||
if (widget->helplabel == NULL)
|
||||
{
|
||||
widget->helplabel = "";
|
||||
}
|
||||
|
||||
// When helplabel is not set for widget draw nothing
|
||||
|
||||
if (widget->is_helplabel_set != 1)
|
||||
{
|
||||
TXT_SetHelpLabel(widget, "");
|
||||
}
|
||||
|
||||
// When in active window no widget is hovering or focused deactivate helplabel
|
||||
|
||||
if (!TXT_ContainsWidget(active_window, widget))
|
||||
{
|
||||
TXT_DrawHelpLabel("");
|
||||
}
|
||||
|
||||
if (widget->focused)
|
||||
{
|
||||
TXT_FGColor(TXT_COLOR_BLACK);
|
||||
TXT_BGColor(TXT_COLOR_GREY, 0);
|
||||
|
||||
// Set helplabel when widget focused
|
||||
|
||||
if (!TXT_HoveringOverWidget(active_window) && widget->is_helplabel_set == 1)
|
||||
{
|
||||
TXT_DrawHelpLabel(widget->helplabel);
|
||||
}
|
||||
}
|
||||
|
||||
else if (TXT_HoveringOverWidget(widget))
|
||||
{
|
||||
TXT_BGColor(TXT_HOVER_BACKGROUND, 0);
|
||||
}
|
||||
|
||||
if (TXT_HoveringOverWidget(widget) && widget->is_helplabel_set == 1)
|
||||
{
|
||||
// Set helplabel when mouse hovering over widget
|
||||
|
||||
TXT_DrawHelpLabel(widget->helplabel);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use normal window background.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_WIDGET_H
|
||||
#define TXT_WIDGET_H
|
||||
|
||||
/**
|
||||
* @file txt_widget.h
|
||||
*
|
||||
* Base "widget" GUI component class.
|
||||
*/
|
||||
|
||||
#ifndef DOXYGEN
|
||||
|
||||
#define TXT_UNCAST_ARG_NAME(name) uncast_ ## name
|
||||
#define TXT_UNCAST_ARG(name) void * TXT_UNCAST_ARG_NAME(name)
|
||||
#define TXT_CAST_ARG(type, name) type *name = (type *) uncast_ ## name
|
||||
|
||||
#else
|
||||
|
||||
#define TXT_UNCAST_ARG(name) txt_widget_t *name
|
||||
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TXT_VERT_TOP,
|
||||
TXT_VERT_CENTER,
|
||||
TXT_VERT_BOTTOM,
|
||||
} txt_vert_align_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TXT_HORIZ_LEFT,
|
||||
TXT_HORIZ_CENTER,
|
||||
TXT_HORIZ_RIGHT,
|
||||
} txt_horiz_align_t;
|
||||
|
||||
/**
|
||||
* A GUI widget.
|
||||
*
|
||||
* A widget is an individual component of a GUI. Various different widget
|
||||
* types exist.
|
||||
*
|
||||
* Widgets may emit signals. The types of signal emitted by a widget
|
||||
* depend on the type of the widget. It is possible to be notified
|
||||
* when a signal occurs using the @ref TXT_SignalConnect function.
|
||||
*/
|
||||
|
||||
typedef struct txt_widget_s txt_widget_t;
|
||||
|
||||
typedef struct txt_widget_class_s txt_widget_class_t;
|
||||
typedef struct txt_callback_table_s txt_callback_table_t;
|
||||
|
||||
typedef void (*TxtWidgetSizeCalc)(TXT_UNCAST_ARG(widget));
|
||||
typedef void (*TxtWidgetDrawer)(TXT_UNCAST_ARG(widget));
|
||||
typedef void (*TxtWidgetDestroy)(TXT_UNCAST_ARG(widget));
|
||||
typedef int (*TxtWidgetKeyPress)(TXT_UNCAST_ARG(widget), int key);
|
||||
typedef void (*TxtWidgetSignalFunc)(TXT_UNCAST_ARG(widget), void *user_data);
|
||||
typedef void (*TxtMousePressFunc)(TXT_UNCAST_ARG(widget), int x, int y, int b);
|
||||
typedef void (*TxtWidgetLayoutFunc)(TXT_UNCAST_ARG(widget));
|
||||
typedef int (*TxtWidgetSelectableFunc)(TXT_UNCAST_ARG(widget));
|
||||
typedef void (*TxtWidgetFocusFunc)(TXT_UNCAST_ARG(widget), int focused);
|
||||
|
||||
struct txt_widget_class_s
|
||||
{
|
||||
TxtWidgetSelectableFunc selectable;
|
||||
TxtWidgetSizeCalc size_calc;
|
||||
TxtWidgetDrawer drawer;
|
||||
TxtWidgetKeyPress key_press;
|
||||
TxtWidgetDestroy destructor;
|
||||
TxtMousePressFunc mouse_press;
|
||||
TxtWidgetLayoutFunc layout;
|
||||
TxtWidgetFocusFunc focus_change;
|
||||
};
|
||||
|
||||
struct txt_widget_s
|
||||
{
|
||||
txt_widget_class_t *widget_class;
|
||||
txt_callback_table_t *callback_table;
|
||||
int visible;
|
||||
txt_horiz_align_t align;
|
||||
int focused;
|
||||
|
||||
// These are set automatically when the window is drawn and should
|
||||
// not be set manually.
|
||||
|
||||
int x, y;
|
||||
unsigned int w, h;
|
||||
|
||||
// Pointer up to parent widget that contains this widget.
|
||||
|
||||
txt_widget_t *parent;
|
||||
|
||||
// Set helplabel to widget
|
||||
|
||||
const char* helplabel;
|
||||
|
||||
// Call helplabel draw function only when helplabel is set for widget
|
||||
|
||||
int is_helplabel_set;
|
||||
};
|
||||
|
||||
void TXT_InitWidget(TXT_UNCAST_ARG(widget), txt_widget_class_t *widget_class);
|
||||
void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget));
|
||||
void TXT_DrawWidget(TXT_UNCAST_ARG(widget));
|
||||
void TXT_EmitSignal(TXT_UNCAST_ARG(widget), const char *signal_name);
|
||||
int TXT_WidgetKeyPress(TXT_UNCAST_ARG(widget), int key);
|
||||
void TXT_WidgetMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b);
|
||||
void TXT_DestroyWidget(TXT_UNCAST_ARG(widget));
|
||||
void TXT_LayoutWidget(TXT_UNCAST_ARG(widget));
|
||||
int TXT_AlwaysSelectable(TXT_UNCAST_ARG(widget));
|
||||
int TXT_NeverSelectable(TXT_UNCAST_ARG(widget));
|
||||
void TXT_SetWidgetFocus(TXT_UNCAST_ARG(widget), int focused);
|
||||
|
||||
/**
|
||||
* Set a callback function to be invoked when a signal occurs.
|
||||
*
|
||||
* @param widget The widget to watch.
|
||||
* @param signal_name The signal to watch.
|
||||
* @param func The callback function to invoke.
|
||||
* @param user_data User-specified pointer to pass to the callback function.
|
||||
*/
|
||||
|
||||
void TXT_SignalConnect(TXT_UNCAST_ARG(widget), const char *signal_name,
|
||||
TxtWidgetSignalFunc func, void *user_data);
|
||||
|
||||
/**
|
||||
* Set the policy for how a widget should be aligned within a table.
|
||||
* By default, widgets are aligned to the left of the column.
|
||||
*
|
||||
* @param widget The widget.
|
||||
* @param horiz_align The alignment to use.
|
||||
*/
|
||||
|
||||
void TXT_SetWidgetAlign(TXT_UNCAST_ARG(widget), txt_horiz_align_t horiz_align);
|
||||
|
||||
/**
|
||||
* Query whether a widget is selectable with the cursor.
|
||||
*
|
||||
* @param widget The widget.
|
||||
* @return Non-zero if the widget is selectable.
|
||||
*/
|
||||
|
||||
int TXT_SelectableWidget(TXT_UNCAST_ARG(widget));
|
||||
|
||||
/**
|
||||
* Query whether the mouse is hovering over the specified widget.
|
||||
*
|
||||
* @param widget The widget.
|
||||
* @return Non-zero if the mouse cursor is over the widget.
|
||||
*/
|
||||
|
||||
int TXT_HoveringOverWidget(TXT_UNCAST_ARG(widget));
|
||||
|
||||
/**
|
||||
* Set the background to draw the specified widget, depending on
|
||||
* whether it is selected and the mouse is hovering over it.
|
||||
*
|
||||
* @param widget The widget.
|
||||
*/
|
||||
|
||||
void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget));
|
||||
|
||||
/**
|
||||
* Query whether the specified widget is contained within another
|
||||
* widget.
|
||||
*
|
||||
* @param haystack The widget that might contain needle.
|
||||
* @param needle The widget being queried.
|
||||
*/
|
||||
|
||||
int TXT_ContainsWidget(TXT_UNCAST_ARG(haystack), TXT_UNCAST_ARG(needle));
|
||||
|
||||
/**
|
||||
* Set helplabel on left side of bottom banner
|
||||
*
|
||||
* @ param widget The widget
|
||||
* @ param helplabel The helplabel to show on bottom banner
|
||||
*/
|
||||
|
||||
void TXT_SetHelpLabel(TXT_UNCAST_ARG(widget), const char* helplabel);
|
||||
|
||||
#endif /* #ifndef TXT_WIDGET_H */
|
||||
|
||||
@@ -0,0 +1,687 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_label.h"
|
||||
#include "txt_desktop.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_separator.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
void TXT_SetWindowAction(txt_window_t *window,
|
||||
txt_horiz_align_t position,
|
||||
TXT_UNCAST_ARG(action))
|
||||
{
|
||||
TXT_CAST_ARG(txt_widget_t, action);
|
||||
|
||||
if (window->actions[position] != NULL)
|
||||
{
|
||||
TXT_DestroyWidget(window->actions[position]);
|
||||
}
|
||||
|
||||
window->actions[position] = action;
|
||||
|
||||
// Maintain parent pointer.
|
||||
|
||||
if (action != NULL)
|
||||
{
|
||||
action->parent = &window->table.widget;
|
||||
}
|
||||
}
|
||||
|
||||
txt_window_t *TXT_NewCustomWindow(const char *title, int titlecolor, int active_bgcolor, int inactive_bgcolor, int active_fgcolor, int inactive_fgcolor, int framecolor, int sepcolor)
|
||||
{
|
||||
int i;
|
||||
|
||||
txt_window_t* win;
|
||||
|
||||
win = malloc(sizeof(txt_window_t));
|
||||
|
||||
TXT_InitTable(&win->table, 1);
|
||||
|
||||
if (title == NULL)
|
||||
{
|
||||
win->title = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
win->title = strdup(title);
|
||||
}
|
||||
|
||||
win->x = TXT_SCREEN_W / 2;
|
||||
win->y = TXT_SCREEN_H / 2;
|
||||
win->horiz_align = TXT_HORIZ_CENTER;
|
||||
win->vert_align = TXT_VERT_CENTER;
|
||||
win->key_listener = NULL;
|
||||
win->mouse_listener = NULL;
|
||||
win->help_url = NULL;
|
||||
win->titlecolor = titlecolor;
|
||||
win->active_bgcolor = active_bgcolor;
|
||||
win->inactive_bgcolor = inactive_bgcolor;
|
||||
win->active_fgcolor = active_fgcolor;
|
||||
win->inactive_fgcolor = inactive_fgcolor;
|
||||
win->framecolor = framecolor;
|
||||
win->sepcolor = sepcolor;
|
||||
win->customwin = 1;
|
||||
|
||||
TXT_AddWidget(win, TXT_NewSeparator(NULL));
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
win->actions[i] = NULL;
|
||||
}
|
||||
|
||||
TXT_AddDesktopWindow(win);
|
||||
|
||||
// Default actions
|
||||
|
||||
TXT_SetWindowAction(win, TXT_HORIZ_LEFT, TXT_NewWindowEscapeAction(win));
|
||||
TXT_SetWindowAction(win, TXT_HORIZ_RIGHT, TXT_NewWindowSelectAction(win));
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
txt_window_t *TXT_NewWindow(const char *title)
|
||||
{
|
||||
int i;
|
||||
|
||||
txt_window_t *win;
|
||||
|
||||
win = malloc(sizeof(txt_window_t));
|
||||
|
||||
TXT_InitTable(&win->table, 1);
|
||||
|
||||
if (title == NULL)
|
||||
{
|
||||
win->title = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
win->title = strdup(title);
|
||||
}
|
||||
|
||||
win->x = TXT_SCREEN_W / 2;
|
||||
win->y = TXT_SCREEN_H / 2;
|
||||
win->horiz_align = TXT_HORIZ_CENTER;
|
||||
win->vert_align = TXT_VERT_CENTER;
|
||||
win->key_listener = NULL;
|
||||
win->mouse_listener = NULL;
|
||||
win->help_url = NULL;
|
||||
win->customwin = 0;
|
||||
|
||||
TXT_AddWidget(win, TXT_NewSeparator(NULL));
|
||||
|
||||
for (i=0; i<3; ++i)
|
||||
{
|
||||
win->actions[i] = NULL;
|
||||
}
|
||||
|
||||
TXT_AddDesktopWindow(win);
|
||||
|
||||
// Default actions
|
||||
|
||||
TXT_SetWindowAction(win, TXT_HORIZ_LEFT, TXT_NewWindowEscapeAction(win));
|
||||
TXT_SetWindowAction(win, TXT_HORIZ_RIGHT, TXT_NewWindowSelectAction(win));
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
void TXT_CloseWindow(txt_window_t *window)
|
||||
{
|
||||
int i;
|
||||
|
||||
TXT_EmitSignal(window, "closed");
|
||||
TXT_RemoveDesktopWindow(window);
|
||||
|
||||
free(window->title);
|
||||
|
||||
// Destroy all actions
|
||||
|
||||
for (i=0; i<3; ++i)
|
||||
{
|
||||
if (window->actions[i] != NULL)
|
||||
{
|
||||
TXT_DestroyWidget(window->actions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy table and window
|
||||
|
||||
TXT_DestroyWidget(window);
|
||||
}
|
||||
|
||||
static void CalcWindowPosition(txt_window_t *window)
|
||||
{
|
||||
switch (window->horiz_align)
|
||||
{
|
||||
case TXT_HORIZ_LEFT:
|
||||
window->window_x = window->x;
|
||||
break;
|
||||
case TXT_HORIZ_CENTER:
|
||||
window->window_x = window->x - (window->window_w / 2);
|
||||
break;
|
||||
case TXT_HORIZ_RIGHT:
|
||||
window->window_x = window->x - (window->window_w - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (window->vert_align)
|
||||
{
|
||||
case TXT_VERT_TOP:
|
||||
window->window_y = window->y;
|
||||
break;
|
||||
case TXT_VERT_CENTER:
|
||||
window->window_y = window->y - (window->window_h / 2);
|
||||
break;
|
||||
case TXT_VERT_BOTTOM:
|
||||
window->window_y = window->y - (window->window_h - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void LayoutActionArea(txt_window_t *window)
|
||||
{
|
||||
txt_widget_t *widget;
|
||||
int space_available;
|
||||
int space_left_offset;
|
||||
|
||||
// We need to calculate the available horizontal space for the center
|
||||
// action widget, so that we can center it within it.
|
||||
// To start with, we have the entire action area available.
|
||||
|
||||
space_available = window->window_w;
|
||||
space_left_offset = 0;
|
||||
|
||||
// Left action
|
||||
|
||||
if (window->actions[TXT_HORIZ_LEFT] != NULL)
|
||||
{
|
||||
widget = window->actions[TXT_HORIZ_LEFT];
|
||||
|
||||
TXT_CalcWidgetSize(widget);
|
||||
|
||||
widget->x = window->window_x + 1;
|
||||
widget->y = window->window_y + window->window_h - widget->h - 1;
|
||||
|
||||
// Adjust available space:
|
||||
space_available -= widget->w;
|
||||
space_left_offset += widget->w;
|
||||
|
||||
TXT_LayoutWidget(widget);
|
||||
}
|
||||
|
||||
// Draw the right action
|
||||
|
||||
if (window->actions[TXT_HORIZ_RIGHT] != NULL)
|
||||
{
|
||||
widget = window->actions[TXT_HORIZ_RIGHT];
|
||||
|
||||
TXT_CalcWidgetSize(widget);
|
||||
|
||||
widget->x = window->window_x + window->window_w - 1 - widget->w;
|
||||
widget->y = window->window_y + window->window_h - widget->h - 1;
|
||||
|
||||
// Adjust available space:
|
||||
space_available -= widget->w;
|
||||
|
||||
TXT_LayoutWidget(widget);
|
||||
}
|
||||
|
||||
// Draw the center action
|
||||
|
||||
if (window->actions[TXT_HORIZ_CENTER] != NULL)
|
||||
{
|
||||
widget = window->actions[TXT_HORIZ_CENTER];
|
||||
|
||||
TXT_CalcWidgetSize(widget);
|
||||
|
||||
// The left and right widgets have left a space sandwiched between
|
||||
// them. Center this widget within that space.
|
||||
widget->x = window->window_x
|
||||
+ space_left_offset
|
||||
+ (space_available - widget->w) / 2;
|
||||
widget->y = window->window_y + window->window_h - widget->h - 1;
|
||||
|
||||
TXT_LayoutWidget(widget);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawActionArea(txt_window_t *window)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<3; ++i)
|
||||
{
|
||||
if (window->actions[i] != NULL)
|
||||
{
|
||||
TXT_DrawWidget(window->actions[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CalcActionAreaSize(txt_window_t *window,
|
||||
unsigned int *w, unsigned int *h)
|
||||
{
|
||||
txt_widget_t *widget;
|
||||
int i;
|
||||
|
||||
*w = 0;
|
||||
*h = 0;
|
||||
|
||||
// Calculate the width of all the action widgets and use this
|
||||
// to create an overall min. width of the action area
|
||||
|
||||
for (i=0; i<3; ++i)
|
||||
{
|
||||
widget = (txt_widget_t *) window->actions[i];
|
||||
|
||||
if (widget != NULL)
|
||||
{
|
||||
TXT_CalcWidgetSize(widget);
|
||||
*w += widget->w;
|
||||
|
||||
if (widget->h > *h)
|
||||
{
|
||||
*h = widget->h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sets size and position of all widgets in a window
|
||||
|
||||
void TXT_LayoutWindow(txt_window_t *window)
|
||||
{
|
||||
txt_widget_t *widgets = (txt_widget_t *) window;
|
||||
unsigned int widgets_w;
|
||||
unsigned int actionarea_w, actionarea_h;
|
||||
|
||||
// Calculate size of table
|
||||
|
||||
TXT_CalcWidgetSize(window);
|
||||
|
||||
// Widgets area: add one character of padding on each side
|
||||
widgets_w = widgets->w + 2;
|
||||
|
||||
// Calculate the size of the action area
|
||||
// Make window wide enough to action area
|
||||
|
||||
CalcActionAreaSize(window, &actionarea_w, &actionarea_h);
|
||||
|
||||
if (actionarea_w > widgets_w)
|
||||
widgets_w = actionarea_w - 2;
|
||||
|
||||
// Set the window size based on widgets_w
|
||||
|
||||
window->window_w = widgets_w + 2;
|
||||
window->window_h = widgets->h + 1;
|
||||
|
||||
// If the window has a title, add an extra two lines
|
||||
|
||||
if (window->title != NULL)
|
||||
{
|
||||
window->window_h += 2;
|
||||
}
|
||||
|
||||
// If the window has an action area, add extra lines
|
||||
|
||||
if (actionarea_h > 0)
|
||||
{
|
||||
window->window_h += actionarea_h + 1;
|
||||
}
|
||||
|
||||
// Use the x,y position as the centerpoint and find the location to
|
||||
// draw the window.
|
||||
|
||||
CalcWindowPosition(window);
|
||||
|
||||
// Set the table size and position
|
||||
|
||||
widgets->w = widgets_w - 2;
|
||||
// widgets->h (already set)
|
||||
widgets->x = window->window_x + 2;
|
||||
widgets->y = window->window_y;
|
||||
|
||||
if (window->title != NULL)
|
||||
{
|
||||
widgets->y += 2;
|
||||
}
|
||||
|
||||
// Layout the table and action area
|
||||
|
||||
LayoutActionArea(window);
|
||||
TXT_LayoutWidget(widgets);
|
||||
}
|
||||
|
||||
void TXT_DrawWindow(txt_window_t *window)
|
||||
{
|
||||
txt_widget_t *widgets;
|
||||
|
||||
TXT_LayoutWindow(window);
|
||||
|
||||
if (window->table.widget.focused && window->customwin != 1)
|
||||
{
|
||||
TXT_BGColor(TXT_ACTIVE_WINDOW_BACKGROUND, 0);
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
|
||||
}
|
||||
else if (window->customwin != 1)
|
||||
{
|
||||
TXT_BGColor(TXT_INACTIVE_WINDOW_BACKGROUND, 0);
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
|
||||
}
|
||||
|
||||
if (window->table.widget.focused && window->customwin == 1)
|
||||
{
|
||||
TXT_BGColor(window->active_bgcolor, 0);
|
||||
TXT_FGColor(window->active_fgcolor);
|
||||
}
|
||||
else if (window->customwin == 1)
|
||||
{
|
||||
TXT_BGColor(window->inactive_bgcolor, 0);
|
||||
TXT_FGColor(window->inactive_fgcolor);
|
||||
}
|
||||
|
||||
// Draw the window
|
||||
|
||||
TXT_DrawWindowFrame(window->title,
|
||||
window->window_x, window->window_y,
|
||||
window->window_w, window->window_h,
|
||||
window->titlecolor, window->framecolor,
|
||||
window->customwin);
|
||||
|
||||
// Draw all widgets
|
||||
|
||||
TXT_DrawWidget(window);
|
||||
|
||||
// Draw an action area, if we have one
|
||||
|
||||
widgets = (txt_widget_t *) window;
|
||||
|
||||
if (widgets->y + widgets->h < window->window_y + window->window_h - 1)
|
||||
{
|
||||
// Separator for action area
|
||||
|
||||
TXT_DrawSeparator(window->window_x, widgets->y + widgets->h,
|
||||
window->window_w, window->sepcolor, window->customwin);
|
||||
|
||||
// Action area at the window bottom
|
||||
|
||||
DrawActionArea(window);
|
||||
}
|
||||
}
|
||||
|
||||
void TXT_SetWindowPosition(txt_window_t *window,
|
||||
txt_horiz_align_t horiz_align,
|
||||
txt_vert_align_t vert_align,
|
||||
int x, int y)
|
||||
{
|
||||
window->vert_align = vert_align;
|
||||
window->horiz_align = horiz_align;
|
||||
window->x = x;
|
||||
window->y = y;
|
||||
}
|
||||
|
||||
static int MouseButtonPress(txt_window_t *window, int b)
|
||||
{
|
||||
int x, y;
|
||||
int i;
|
||||
txt_widget_t *widgets;
|
||||
txt_widget_t *widget;
|
||||
|
||||
// Lay out the window, set positions and sizes of all widgets
|
||||
|
||||
TXT_LayoutWindow(window);
|
||||
|
||||
// Get the current mouse position
|
||||
|
||||
TXT_GetMousePosition(&x, &y);
|
||||
|
||||
// Try the mouse button listener
|
||||
// This happens whether it is in the window range or not
|
||||
|
||||
if (window->mouse_listener != NULL)
|
||||
{
|
||||
// Mouse listener can eat button presses
|
||||
|
||||
if (window->mouse_listener(window, x, y, b,
|
||||
window->mouse_listener_data))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Is it within the table range?
|
||||
|
||||
widgets = (txt_widget_t *) window;
|
||||
|
||||
if (x >= widgets->x && x < (signed) (widgets->x + widgets->w)
|
||||
&& y >= widgets->y && y < (signed) (widgets->y + widgets->h))
|
||||
{
|
||||
TXT_WidgetMousePress(window, x, y, b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Was one of the action area buttons pressed?
|
||||
|
||||
for (i=0; i<3; ++i)
|
||||
{
|
||||
widget = window->actions[i];
|
||||
|
||||
if (widget != NULL
|
||||
&& x >= widget->x && x < (signed) (widget->x + widget->w)
|
||||
&& y >= widget->y && y < (signed) (widget->y + widget->h))
|
||||
{
|
||||
int was_focused;
|
||||
|
||||
// Main table temporarily loses focus when action area button
|
||||
// is clicked. This way, any active input boxes that depend
|
||||
// on having focus will save their values before the
|
||||
// action is performed.
|
||||
|
||||
was_focused = window->table.widget.focused;
|
||||
TXT_SetWidgetFocus(window, 0);
|
||||
TXT_SetWidgetFocus(window, was_focused);
|
||||
|
||||
// Pass through mouse press.
|
||||
|
||||
TXT_WidgetMousePress(widget, x, y, b);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TXT_WindowKeyPress(txt_window_t *window, int c)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Is this a mouse button ?
|
||||
|
||||
if (c >= TXT_MOUSE_BASE && c < TXT_MOUSE_BASE + TXT_MAX_MOUSE_BUTTONS)
|
||||
{
|
||||
return MouseButtonPress(window, c);
|
||||
}
|
||||
|
||||
// Try the window key spy
|
||||
|
||||
if (window->key_listener != NULL)
|
||||
{
|
||||
// key listener can eat keys
|
||||
|
||||
if (window->key_listener(window, c, window->key_listener_data))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Send to the currently selected widget:
|
||||
|
||||
if (TXT_WidgetKeyPress(window, c))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Try all of the action buttons
|
||||
|
||||
for (i=0; i<3; ++i)
|
||||
{
|
||||
if (window->actions[i] != NULL
|
||||
&& TXT_WidgetKeyPress(window->actions[i], c))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TXT_SetKeyListener(txt_window_t *window, TxtWindowKeyPress key_listener,
|
||||
void *user_data)
|
||||
{
|
||||
window->key_listener = key_listener;
|
||||
window->key_listener_data = user_data;
|
||||
}
|
||||
|
||||
void TXT_SetMouseListener(txt_window_t *window,
|
||||
TxtWindowMousePress mouse_listener,
|
||||
void *user_data)
|
||||
{
|
||||
window->mouse_listener = mouse_listener;
|
||||
window->mouse_listener_data = user_data;
|
||||
}
|
||||
|
||||
void TXT_SetWindowFocus(txt_window_t *window, int focused)
|
||||
{
|
||||
TXT_SetWidgetFocus(window, focused);
|
||||
}
|
||||
|
||||
void TXT_SetWindowHelpURL(txt_window_t *window, const char *help_url)
|
||||
{
|
||||
window->help_url = help_url;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void TXT_OpenURL(const char *url)
|
||||
{
|
||||
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void TXT_OpenURL(const char *url)
|
||||
{
|
||||
char *cmd;
|
||||
size_t cmd_len;
|
||||
int retval;
|
||||
|
||||
cmd_len = strlen(url) + 30;
|
||||
cmd = malloc(cmd_len);
|
||||
|
||||
#if defined(__MACOSX__)
|
||||
TXT_snprintf(cmd, cmd_len, "open \"%s\"", url);
|
||||
#else
|
||||
// The Unix situation sucks as usual, but the closest thing to a
|
||||
// standard that exists is the xdg-utils package.
|
||||
if (system("xdg-open --version 2>/dev/null") != 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"xdg-utils is not installed. Can't open this URL:\n%s\n", url);
|
||||
free(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
TXT_snprintf(cmd, cmd_len, "xdg-open \"%s\"", url);
|
||||
#endif
|
||||
|
||||
retval = system(cmd);
|
||||
free(cmd);
|
||||
if (retval != 0)
|
||||
{
|
||||
fprintf(stderr, "TXT_OpenURL: error executing '%s'; return code %d\n",
|
||||
cmd, retval);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #ifndef _WIN32 */
|
||||
|
||||
void TXT_OpenWindowHelpURL(txt_window_t *window)
|
||||
{
|
||||
if (window->help_url != NULL)
|
||||
{
|
||||
TXT_OpenURL(window->help_url);
|
||||
}
|
||||
}
|
||||
|
||||
txt_window_t* TXT_CustomMessageBox(const char* title, const char* message, int titlecolor, int active_bgcolor, int inactive_bgcolor, int active_fgcolor, int inactive_fgcolor, int framecolor, int sepcolor, ...)
|
||||
{
|
||||
txt_window_t* window;
|
||||
char buf[256];
|
||||
va_list args;
|
||||
|
||||
va_start(args, sepcolor);
|
||||
TXT_vsnprintf(buf, sizeof(buf), message, args);
|
||||
va_end(args);
|
||||
|
||||
window = TXT_NewCustomWindow(title, titlecolor, active_bgcolor, inactive_bgcolor, active_fgcolor, inactive_fgcolor, framecolor, sepcolor);
|
||||
TXT_AddWidget(window, TXT_NewLabel(buf));
|
||||
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL);
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_CENTER,
|
||||
TXT_NewWindowEscapeAction(window));
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
txt_window_t *TXT_MessageBox(const char *title, const char *message, ...)
|
||||
{
|
||||
txt_window_t *window;
|
||||
char buf[256];
|
||||
va_list args;
|
||||
|
||||
va_start(args, message);
|
||||
TXT_vsnprintf(buf, sizeof(buf), message, args);
|
||||
va_end(args);
|
||||
|
||||
window = TXT_NewWindow(title);
|
||||
TXT_AddWidget(window, TXT_NewLabel(buf));
|
||||
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL);
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_CENTER,
|
||||
TXT_NewWindowEscapeAction(window));
|
||||
TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_WINDOW_H
|
||||
#define TXT_WINDOW_H
|
||||
|
||||
/**
|
||||
* @file txt_window.h
|
||||
*
|
||||
* Windows.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A window.
|
||||
*
|
||||
* A window contains widgets, and may also be treated as a table
|
||||
* (@ref txt_table_t) containing a single column.
|
||||
*
|
||||
* Windows can be created using @ref TXT_NewWindow and closed using
|
||||
* @ref TXT_CloseWindow. When a window is closed, it emits the
|
||||
* "closed" signal.
|
||||
*
|
||||
* In addition to the widgets within a window, windows also have
|
||||
* a "tray" area at their bottom containing window action widgets.
|
||||
* These widgets allow keyboard shortcuts to trigger common actions.
|
||||
* Each window has three slots for keyboard shortcuts. By default,
|
||||
* the left slot contains an action to close the window when the
|
||||
* escape button is pressed, while the right slot contains an
|
||||
* action to activate the currently-selected widget.
|
||||
*/
|
||||
|
||||
typedef struct txt_window_s txt_window_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
#include "txt_table.h"
|
||||
#include "txt_window_action.h"
|
||||
|
||||
// Callback function for window key presses
|
||||
|
||||
typedef int (*TxtWindowKeyPress)(txt_window_t *window, int key,
|
||||
void *user_data);
|
||||
typedef int (*TxtWindowMousePress)(txt_window_t *window,
|
||||
int x, int y, int b,
|
||||
void *user_data);
|
||||
|
||||
struct txt_window_s
|
||||
{
|
||||
// Base class: all windows are tables with one column.
|
||||
|
||||
txt_table_t table;
|
||||
|
||||
// Window title
|
||||
|
||||
char *title;
|
||||
|
||||
// Screen coordinates of the window
|
||||
|
||||
txt_vert_align_t vert_align;
|
||||
txt_horiz_align_t horiz_align;
|
||||
int x, y;
|
||||
|
||||
// Actions that appear in the box at the bottom of the window
|
||||
|
||||
txt_widget_t *actions[3];
|
||||
|
||||
// Callback functions to invoke when keys/mouse buttons are pressed
|
||||
|
||||
TxtWindowKeyPress key_listener;
|
||||
void *key_listener_data;
|
||||
TxtWindowMousePress mouse_listener;
|
||||
void *mouse_listener_data;
|
||||
|
||||
// These are set automatically when the window is drawn
|
||||
|
||||
int window_x, window_y;
|
||||
unsigned int window_w, window_h;
|
||||
|
||||
// URL of a webpage with help about this window. If set, a help key
|
||||
// indicator is shown while this window is active.
|
||||
|
||||
const char *help_url;
|
||||
|
||||
// Title color of the window
|
||||
|
||||
int titlecolor;
|
||||
|
||||
// Background color of the active window
|
||||
|
||||
int active_bgcolor;
|
||||
|
||||
// Background color of the inactive window
|
||||
|
||||
int inactive_bgcolor;
|
||||
|
||||
// Foreground color of the active window
|
||||
|
||||
int active_fgcolor;
|
||||
|
||||
// Foreground color of the inactive window
|
||||
|
||||
int inactive_fgcolor;
|
||||
|
||||
// Frame color of the window
|
||||
|
||||
int framecolor;
|
||||
|
||||
// Seperator color of the window
|
||||
|
||||
int sepcolor;
|
||||
|
||||
// True when TXT_NewCustomWindow is set
|
||||
|
||||
int customwin;
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a new custom window.
|
||||
*
|
||||
* @param title Title to display in the titlebar of the new window
|
||||
* (UTF-8 format).
|
||||
* @param titlecolor Set color of title to window.
|
||||
* @param active_bgcolor Set color of background to active window.
|
||||
* @param inactive_bgcolor Set color of background to inactive window.
|
||||
* @param active_fgcolor Set color of foreground to active window.
|
||||
* @param inactive_fgcolor Set color of foreground to inactive window.
|
||||
* @param framecolor Set color of frame to window.
|
||||
* @param sepcolor Set color of separator to window.
|
||||
* @return Pointer to a new @ref txt_window_t structure.
|
||||
* representing the new window.
|
||||
*/
|
||||
|
||||
txt_window_t* TXT_NewCustomWindow(const char* title, int titlecolor, int active_bgcolor, int inactive_bgcolor, int active_fgcolor, int inactive_fgcolor, int framecolor, int sepcolor);
|
||||
|
||||
/**
|
||||
* Open a new window.
|
||||
*
|
||||
* @param title Title to display in the titlebar of the new window
|
||||
* (UTF-8 format).
|
||||
* @return Pointer to a new @ref txt_window_t structure
|
||||
* representing the new window.
|
||||
*/
|
||||
|
||||
txt_window_t *TXT_NewWindow(const char *title);
|
||||
|
||||
/**
|
||||
* Close a window.
|
||||
*
|
||||
* @param window Tine window to close.
|
||||
*/
|
||||
|
||||
void TXT_CloseWindow(txt_window_t *window);
|
||||
|
||||
/**
|
||||
* Set the position of a window on the screen.
|
||||
*
|
||||
* The position is specified as a pair of x, y, coordinates on the
|
||||
* screen. These specify the position of a particular point on the
|
||||
* window. The following are some examples:
|
||||
*
|
||||
* <code>
|
||||
* // Centered on the screen:
|
||||
*
|
||||
* TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_CENTER,
|
||||
* TXT_SCREEN_W / 2, TXT_SCREEN_H / 2);
|
||||
*
|
||||
* // Horizontally centered, with top of the window on line 6:
|
||||
*
|
||||
* TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP,
|
||||
* TXT_SCREEN_W / 2, 6);
|
||||
*
|
||||
* // Top-left of window at 20, 6:
|
||||
*
|
||||
* TXT_SetWindowPosition(window, TXT_HORIZ_LEFT, TXT_VERT_TOP, 20, 6);
|
||||
* </code>
|
||||
*
|
||||
* @param window The window.
|
||||
* @param horiz_align Horizontal location on the window for the X
|
||||
* position.
|
||||
* @param vert_align Vertical location on the window for the Y position.
|
||||
* @param x X coordinate (horizontal axis) for window position.
|
||||
* @param y Y coordinate (vertical axis) for window position.
|
||||
*/
|
||||
|
||||
void TXT_SetWindowPosition(txt_window_t *window,
|
||||
txt_horiz_align_t horiz_align,
|
||||
txt_vert_align_t vert_align,
|
||||
int x, int y);
|
||||
|
||||
/**
|
||||
* Set a window action for a given window.
|
||||
*
|
||||
* Each window can have up to three window actions, which provide
|
||||
* keyboard shortcuts that can be used within a given window.
|
||||
*
|
||||
* @param window The window.
|
||||
* @param position The window action slot to set (left, center or right).
|
||||
* @param action The window action widget. If this is NULL, any
|
||||
* current window action in the given slot is removed.
|
||||
*/
|
||||
|
||||
void TXT_SetWindowAction(txt_window_t *window, txt_horiz_align_t position,
|
||||
TXT_UNCAST_ARG(action));
|
||||
|
||||
/**
|
||||
* Set a callback function to be invoked whenever a key is pressed within
|
||||
* a window.
|
||||
*
|
||||
* @param window The window.
|
||||
* @param key_listener Callback function.
|
||||
* @param user_data User-specified pointer to pass to the callback
|
||||
* function.
|
||||
*/
|
||||
|
||||
void TXT_SetKeyListener(txt_window_t *window,
|
||||
TxtWindowKeyPress key_listener,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* Set a callback function to be invoked whenever a mouse button is pressed
|
||||
* within a window.
|
||||
*
|
||||
* @param window The window.
|
||||
* @param mouse_listener Callback function.
|
||||
* @param user_data User-specified pointer to pass to the callback
|
||||
* function.
|
||||
*/
|
||||
|
||||
void TXT_SetMouseListener(txt_window_t *window,
|
||||
TxtWindowMousePress mouse_listener,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* Open a window displaying a message.
|
||||
*
|
||||
* @param title Title of the window (UTF-8 format).
|
||||
* @param message The message to display in the window (UTF-8 format).
|
||||
* @return The new window.
|
||||
*/
|
||||
|
||||
txt_window_t *TXT_MessageBox(const char *title, const char *message, ...);
|
||||
|
||||
/**
|
||||
* Open a window displaying a message.
|
||||
*
|
||||
* @param title Title of the window (UTF-8 format).
|
||||
* @param message The message to display in the window (UTF-8 format).
|
||||
* @param titlecolor Set color of title to window.
|
||||
* @param active_bgcolor Set color of background to active window.
|
||||
* @param inactive_bgcolor Set color of background to inactive window.
|
||||
* @param active_fgcolor Set color of foreground to active window.
|
||||
* @param inactive_fgcolor Set color of foreground to inactive window.
|
||||
* @param framecolor Set color of frame to window.
|
||||
* @param sepcolor Set color of seperator to window.
|
||||
* @return The new window.
|
||||
*/
|
||||
|
||||
txt_window_t* TXT_CustomMessageBox(const char* title, const char* message, int titlecolor, int active_bgcolor, int inactive_bgcolor, int active_fgcolor, int inactive_fgcolor, int framecolor, int sepcolor, ...);
|
||||
|
||||
/**
|
||||
* Set the help URL for the given window.
|
||||
*
|
||||
* @param window The window.
|
||||
* @param help_url String containing URL of the help page for this
|
||||
* window, or NULL to set no help for this window.
|
||||
*/
|
||||
|
||||
void TXT_SetWindowHelpURL(txt_window_t *window, const char *help_url);
|
||||
|
||||
/**
|
||||
* Open the help URL for the given window, if one is set.
|
||||
*
|
||||
* @param window The window.
|
||||
*/
|
||||
|
||||
void TXT_OpenWindowHelpURL(txt_window_t *window);
|
||||
|
||||
#endif /* #ifndef TXT_WINDOW_H */
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_window_action.h"
|
||||
#include "txt_gui.h"
|
||||
#include "txt_io.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_utf8.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
static void TXT_WindowActionSizeCalc(TXT_UNCAST_ARG(action))
|
||||
{
|
||||
TXT_CAST_ARG(txt_window_action_t, action);
|
||||
char buf[10];
|
||||
|
||||
TXT_GetKeyDescription(action->key, buf, sizeof(buf));
|
||||
|
||||
// Width is label length, plus key description length, plus '='
|
||||
// and two surrounding spaces.
|
||||
|
||||
action->widget.w = TXT_UTF8_Strlen(action->label)
|
||||
+ TXT_UTF8_Strlen(buf) + 3;
|
||||
action->widget.h = 1;
|
||||
}
|
||||
|
||||
static void TXT_WindowActionDrawer(TXT_UNCAST_ARG(action))
|
||||
{
|
||||
TXT_CAST_ARG(txt_window_action_t, action);
|
||||
int hovering;
|
||||
char buf[10];
|
||||
|
||||
TXT_GetKeyDescription(action->key, buf, sizeof(buf));
|
||||
|
||||
hovering = TXT_HoveringOverWidget(action);
|
||||
TXT_SetWidgetBG(action);
|
||||
|
||||
TXT_DrawString(" ");
|
||||
TXT_FGColor(hovering ? TXT_COLOR_BRIGHT_WHITE : TXT_COLOR_BRIGHT_GREEN);
|
||||
TXT_DrawString(buf);
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
|
||||
TXT_DrawString("=");
|
||||
|
||||
TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
|
||||
TXT_DrawString(action->label);
|
||||
TXT_DrawString(" ");
|
||||
}
|
||||
|
||||
static void TXT_WindowActionDestructor(TXT_UNCAST_ARG(action))
|
||||
{
|
||||
TXT_CAST_ARG(txt_window_action_t, action);
|
||||
|
||||
free(action->label);
|
||||
}
|
||||
|
||||
static int TXT_WindowActionKeyPress(TXT_UNCAST_ARG(action), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_window_action_t, action);
|
||||
|
||||
if (tolower(key) == tolower(action->key))
|
||||
{
|
||||
TXT_EmitSignal(action, "pressed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TXT_WindowActionMousePress(TXT_UNCAST_ARG(action),
|
||||
int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_window_action_t, action);
|
||||
|
||||
// Simulate a press of the key
|
||||
|
||||
if (b == TXT_MOUSE_LEFT)
|
||||
{
|
||||
TXT_WindowActionKeyPress(action, action->key);
|
||||
}
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_window_action_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_WindowActionSizeCalc,
|
||||
TXT_WindowActionDrawer,
|
||||
TXT_WindowActionKeyPress,
|
||||
TXT_WindowActionDestructor,
|
||||
TXT_WindowActionMousePress,
|
||||
NULL,
|
||||
};
|
||||
|
||||
txt_window_action_t *TXT_NewWindowAction(int key, const char *label)
|
||||
{
|
||||
txt_window_action_t *action;
|
||||
|
||||
action = malloc(sizeof(txt_window_action_t));
|
||||
|
||||
TXT_InitWidget(action, &txt_window_action_class);
|
||||
action->key = key;
|
||||
action->label = strdup(label);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
static void WindowCloseCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(window))
|
||||
{
|
||||
TXT_CAST_ARG(txt_window_t, window);
|
||||
|
||||
TXT_CloseWindow(window);
|
||||
}
|
||||
|
||||
static void WindowSelectCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(window))
|
||||
{
|
||||
TXT_CAST_ARG(txt_window_t, window);
|
||||
|
||||
TXT_WidgetKeyPress(window, KEY_ENTER);
|
||||
}
|
||||
|
||||
// An action with the name "close" the closes the window
|
||||
|
||||
txt_window_action_t *TXT_NewWindowEscapeAction(txt_window_t *window)
|
||||
{
|
||||
txt_window_action_t *action;
|
||||
|
||||
action = TXT_NewWindowAction(KEY_ESCAPE, "Close");
|
||||
TXT_SignalConnect(action, "pressed", WindowCloseCallback, window);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
// Exactly the same as the above, but the button is named "abort"
|
||||
|
||||
txt_window_action_t *TXT_NewWindowAbortAction(txt_window_t *window)
|
||||
{
|
||||
txt_window_action_t *action;
|
||||
|
||||
action = TXT_NewWindowAction(KEY_ESCAPE, "Abort");
|
||||
TXT_SignalConnect(action, "pressed", WindowCloseCallback, window);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
txt_window_action_t *TXT_NewWindowSelectAction(txt_window_t *window)
|
||||
{
|
||||
txt_window_action_t *action;
|
||||
|
||||
action = TXT_NewWindowAction(KEY_ENTER, "Select");
|
||||
TXT_SignalConnect(action, "pressed", WindowSelectCallback, window);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef TXT_WINDOW_ACTION_H
|
||||
#define TXT_WINDOW_ACTION_H
|
||||
|
||||
/**
|
||||
* @file txt_window_action.h
|
||||
*
|
||||
* Window action widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Window action widget.
|
||||
*
|
||||
* A window action is attached to a window and corresponds to a
|
||||
* keyboard shortcut that is active within that window. When the
|
||||
* key is pressed, the action is triggered.
|
||||
*
|
||||
* When a window action is triggered, the "pressed" signal is emitted.
|
||||
*/
|
||||
|
||||
typedef struct txt_window_action_s txt_window_action_t;
|
||||
|
||||
#include "txt_widget.h"
|
||||
#include "txt_window.h"
|
||||
|
||||
struct txt_window_action_s
|
||||
{
|
||||
txt_widget_t widget;
|
||||
char *label;
|
||||
int key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new window action.
|
||||
*
|
||||
* @param key The keyboard key that triggers this action.
|
||||
* @param label Label to display for this action in the tray
|
||||
* at the bottom of the window (UTF-8 format).
|
||||
* @return Pointer to the new window action widget.
|
||||
*/
|
||||
|
||||
txt_window_action_t *TXT_NewWindowAction(int key, const char *label);
|
||||
|
||||
/**
|
||||
* Create a new window action that closes the window when the
|
||||
* escape key is pressed. The label "Close" is used.
|
||||
*
|
||||
* @param window The window to close.
|
||||
* @return Pointer to the new window action widget.
|
||||
*/
|
||||
|
||||
txt_window_action_t *TXT_NewWindowEscapeAction(txt_window_t *window);
|
||||
|
||||
/**
|
||||
* Create a new window action that closes the window when the
|
||||
* escape key is pressed. The label "Abort" is used.
|
||||
*
|
||||
* @param window The window to close.
|
||||
* @return Pointer to the new window action widget.
|
||||
*/
|
||||
|
||||
txt_window_action_t *TXT_NewWindowAbortAction(txt_window_t *window);
|
||||
|
||||
/**
|
||||
* Create a new "select" window action. This does not really do
|
||||
* anything, but reminds the user that "enter" can be pressed to
|
||||
* activate the currently-selected widget.
|
||||
*
|
||||
* @param window The window.
|
||||
* @return Pointer to the new window action widget.
|
||||
*/
|
||||
|
||||
txt_window_action_t *TXT_NewWindowSelectAction(txt_window_t *window);
|
||||
|
||||
#endif /* #ifndef TXT_WINDOW_ACTION_H */
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31205.134
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "textscreen", "textscreen.vcxproj", "{137BAB62-5A11-4928-93F7-BA5DF69BEEE2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{137BAB62-5A11-4928-93F7-BA5DF69BEEE2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{137BAB62-5A11-4928-93F7-BA5DF69BEEE2}.Debug|x64.Build.0 = Debug|x64
|
||||
{137BAB62-5A11-4928-93F7-BA5DF69BEEE2}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{137BAB62-5A11-4928-93F7-BA5DF69BEEE2}.Debug|x86.Build.0 = Debug|Win32
|
||||
{137BAB62-5A11-4928-93F7-BA5DF69BEEE2}.Release|x64.ActiveCfg = Release|x64
|
||||
{137BAB62-5A11-4928-93F7-BA5DF69BEEE2}.Release|x64.Build.0 = Release|x64
|
||||
{137BAB62-5A11-4928-93F7-BA5DF69BEEE2}.Release|x86.ActiveCfg = Release|Win32
|
||||
{137BAB62-5A11-4928-93F7-BA5DF69BEEE2}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {246E79C8-8023-40CF-9E27-4A61BAE7F450}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,208 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\include\txt_button.c" />
|
||||
<ClCompile Include="..\include\txt_checkbox.c" />
|
||||
<ClCompile Include="..\include\txt_conditional.c" />
|
||||
<ClCompile Include="..\include\txt_desktop.c" />
|
||||
<ClCompile Include="..\include\txt_dropdown.c" />
|
||||
<ClCompile Include="..\include\txt_fileselect.c" />
|
||||
<ClCompile Include="..\include\txt_gui.c" />
|
||||
<ClCompile Include="..\include\txt_inputbox.c" />
|
||||
<ClCompile Include="..\include\txt_io.c" />
|
||||
<ClCompile Include="..\include\txt_label.c" />
|
||||
<ClCompile Include="..\include\txt_radiobutton.c" />
|
||||
<ClCompile Include="..\include\txt_scrollpane.c" />
|
||||
<ClCompile Include="..\include\txt_sdl.c" />
|
||||
<ClCompile Include="..\include\txt_separator.c" />
|
||||
<ClCompile Include="..\include\txt_spinctrl.c" />
|
||||
<ClCompile Include="..\include\txt_strut.c" />
|
||||
<ClCompile Include="..\include\txt_table.c" />
|
||||
<ClCompile Include="..\include\txt_utf8.c" />
|
||||
<ClCompile Include="..\include\txt_widget.c" />
|
||||
<ClCompile Include="..\include\txt_window.c" />
|
||||
<ClCompile Include="..\include\txt_window_action.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\doomkeys.h" />
|
||||
<ClInclude Include="..\include\textscreen.h" />
|
||||
<ClInclude Include="..\include\txt_button.h" />
|
||||
<ClInclude Include="..\include\txt_checkbox.h" />
|
||||
<ClInclude Include="..\include\txt_conditional.h" />
|
||||
<ClInclude Include="..\include\txt_desktop.h" />
|
||||
<ClInclude Include="..\include\txt_dropdown.h" />
|
||||
<ClInclude Include="..\include\txt_fileselect.h" />
|
||||
<ClInclude Include="..\include\txt_gui.h" />
|
||||
<ClInclude Include="..\include\txt_inputbox.h" />
|
||||
<ClInclude Include="..\include\txt_io.h" />
|
||||
<ClInclude Include="..\include\txt_label.h" />
|
||||
<ClInclude Include="..\include\txt_main.h" />
|
||||
<ClInclude Include="..\include\txt_radiobutton.h" />
|
||||
<ClInclude Include="..\include\txt_scrollpane.h" />
|
||||
<ClInclude Include="..\include\txt_sdl.h" />
|
||||
<ClInclude Include="..\include\txt_separator.h" />
|
||||
<ClInclude Include="..\include\txt_spinctrl.h" />
|
||||
<ClInclude Include="..\include\txt_strut.h" />
|
||||
<ClInclude Include="..\include\txt_table.h" />
|
||||
<ClInclude Include="..\include\txt_utf8.h" />
|
||||
<ClInclude Include="..\include\txt_widget.h" />
|
||||
<ClInclude Include="..\include\txt_window.h" />
|
||||
<ClInclude Include="..\include\txt_window_action.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{137bab62-5a11-4928-93f7-ba5df69beee2}</ProjectGuid>
|
||||
<RootNamespace>textscreen</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\SDL2-devel-2.28.2-VC\SDL2-2.28.2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>C:\Users\Skynet\source\libs\SDL2-devel-2.0.14-VC\SDL2-2.0.14\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>SDL2main.lib;SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\SDL2-devel-2.28.2-VC\SDL2-2.28.2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>C:\Users\Skynet\source\libs\SDL2-devel-2.0.14-VC\SDL2-2.0.14\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>SDL2main.lib;SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\SDL2-devel-2.28.2-VC\SDL2-2.28.2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>C:\Users\Skynet\Downloads\github\raptor-master32bit\include\SDL2-devel-2.0.14-VC\SDL2-2.0.14\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\SDL2-devel-2.28.2-VC\SDL2-2.28.2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>C:\Users\Skynet\Downloads\github\raptor-master32bit\include\SDL2-devel-2.0.14-VC\SDL2-2.0.14\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Quelldateien">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Ressourcendateien">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Headerdateien">
|
||||
<UniqueIdentifier>{53e021b0-f051-4ee2-a730-80bf8e0ecb1a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\include\txt_button.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_checkbox.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_conditional.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_desktop.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_dropdown.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_fileselect.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_gui.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_inputbox.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_io.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_label.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_radiobutton.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_scrollpane.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_sdl.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_separator.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_spinctrl.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_strut.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_table.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_utf8.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_widget.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_window.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\txt_window_action.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\doomkeys.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\textscreen.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_button.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_checkbox.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_conditional.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_desktop.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_dropdown.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_fileselect.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_gui.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_inputbox.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_io.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_label.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_main.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_radiobutton.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_scrollpane.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_sdl.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_separator.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_spinctrl.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_strut.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_table.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_utf8.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_widget.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_window.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\txt_window_action.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
Reference in new issue
Block a user