Compare commits

...

17 Commits
v069 ... v071

Author SHA1 Message Date
Tim Allen
6c3aec7dc9 Update to v071 release.
byuu says (since v070):

- fixed a regression in the accuracy/compatibility CPU core with IRQ
  masking; fixes World Heroes 2
- fixed OAM address reset on $2100 writes for performance PPU core;
  fixes Mahjongg 2 and others
- DSP-1 always returns high 8-bits of status register; fixes Ace wo
  Nerae! freeze [Jonas Quinn]
- performance core can now take advantage of serial support
- pixel shaders now use a unified XML format; in the future they will
  support multi-pass shaders and textures
- major code restructuring
- first public release of phoenix GUI port
- mightymo's cheat code pack is now an external file for the phoenix
  port
- phoenix port stores cheat codes in XML format as well, unifying all
  file formats to the same markup language
2010-10-22 20:54:59 +11:00
Tim Allen
4016ae1d43 Update to v070r17 release.
byuu says:

- fixes DSP-1 status register for "Ace wo Nerae!"
- fixes IRQ masking for "World Heroes II"
- fixes compilation for the Qt port's debugger
2010-10-20 22:51:19 +11:00
Tim Allen
9e53c51b58 Update to v070r16 release.
(there was no r15 release posted to the WIP thread)

byuu says:

This mostly contains improvements for nall, like path unification.
This should fix FitzRoy's issue with .. on Windows.
2010-10-20 22:51:19 +11:00
Tim Allen
ce2b543679 Update to v070r14 release.
(there was no r13 release posted to the WIP thread)

byuu says:

- nall/string: trim and split functions now take the limit as a template
  parameter for clarity, trim_once variants are removed
  - quotable.trim<1>("\""); //remove quotes from string
  - cheatcode.split<3>(","); //split up to three times, third one is
    a description that may have commas
  - foobar.trim(" "); //remove any and all spaces
- nall/string: added wildcard() and iwildcard() functions for pattern
  matching
- nall/directory: accepts an optional pattern parameter to perform
  wildcard matching
  - lstring cartridges = directory::contents(path, "*.sfc");
  - some people may prefer directory::contents("/path/to/files/*.sfc"),
    but I like not having to build a string when you have the path
    separated already
- nall/qt: removed entirely, now resides in bsnes/ui-qt/template; I do
  intend to replace the check/radio actions with native Qt versions
  later
- bsnes/data: new folder, share the parts that both UIs use; bsnes.ico,
  bsnes.png, bsnes.Desktop, cheats.xml; simplify Makefile install target
- Makefile: install target now creates .bsnes folder and copies
  cheats.xml there for you
- Makefile: gconftool hack removed, not needed for phoenix, will work
  around with Qt later
- will probably make bsnes/Qt read the cheats.xml file externally as
  well, as that file makes each profile 1MB bigger when embedded
  - as such, will probably make bsnes also look in the binary directory
    for that file, so Windows users don't have to copy it to their
    userdata folder
2010-10-20 22:51:19 +11:00
Tim Allen
1a29b59225 Update to v070r12 release.
byuu says:

- removed support for images with copier headers
- phoenix/Windows: Label properly refreshes on text changes, fixes video
  settings sliders
- alt/ppu-performance: fixed mosaic Voffset bug, fixes Super Bowling et al
- alt/cpu: fixed CPU::joylatch() reporting, allows serial applications
  to work with performance profile
- hooked up SNES::cartridge.basename, allows MSU1 and serial support
  with the phoenix UI
- updated UPS patching code for bsnes/Qt, allowing it to compile again,
  hidden config option file.bypassPatchCrc32 was removed
2010-10-20 22:51:19 +11:00
Tim Allen
1926561ced Update to v070r11 release.
byuu says:

- phoenix/All: converted all instances of const char* to const
  nall::string&
  - above used to require: label.setText(string("FPS: ", fps)); but can
    now use: label.setText({"FPS", fps});
  - also avoids the need for the internal implementations to have to
    check for null string pointers
- phoenix/GTK+: no longer disabling double buffering on the viewport.
  Does not cause flickering, and fixes redraw issue on window resize
- phoenix/Qt: like phoenix/GTK+, it will use the default font on the
  menubar as well, so child menu items are consistently sized now
- Linux: file browser can list contents of / and won't let you go
  higher; Windows needs a similar guard for n:/ or \\
- UPS soft-patching support added
- external XML memory map loading support added
- cartridge folder support added: if folder ends in .sfc and there is
  ONE .sfc ROM inside it, it will load the folder as if it were a ROM
- input assignment refreshes text instead of reloading the list, this
  saves your position
  - auto-advance wasn't working very well, will try again later
- input clear all button removed since it's pretty fast now to do
  clear+down:repeat
2010-10-20 22:51:19 +11:00
Tim Allen
e2db2c24fc Update to v070r10 release.
byuu says:

- added workaround to phoenix/Windows to prevent horizontal scrollbar
  always being visible on single-column ListBoxes
- phoenix gains Window::geometry()
- added code to save and restore window positions, as in bsnes/Qt.
  Positions are saved to bsnes-phoenix-geometry.cfg this time
- resizing the main window will keep its position onscreen now

There's one issue with GTK+, if you close a window and then call
gtk_window_get_position(), it returns the previously set position rather
than where you actually placed the window. My easy fix of calling
gtk_window_get_position right before actually closing the window didn't
work, so for now you'll have to live with it.
2010-10-20 22:51:19 +11:00
Tim Allen
8a53e9ed22 Update to v070r09 release.
byuu says:

- removed native OS dialog option, I don't plan to add all the code
  required to make it optional everywhere
- cheat database supported, although it's external now. Either in the
  .bsnes folder or with the binary, named cheats.xml
- cheats.xml is external so that binaries can be much smaller, important
  for multiple profiles
- added "find codes" button to cheat editor (need to gray it out
  permanently if cheats.xml isn't found)
- added cheat database add window, works the same as bsnes/Qt, but it
  will also alert you if you run out of empty cheat slots upon import
- note: I should rename that ok button to "Import"
- hooked up callbacks for multitap/mouse/SS/justifier input
- added mapping for mouse axes and buttons
- used a simplified approach that only lets you map left/middle/right
  buttons, but doesn't need a separate popup window or fake controls
- moved capture mouse command to tools menu
- different from Qt where you'd click inside the main window, meant to
  be safer from accidental capture, escape still releases capture
- made a skeleton for GUI hotkey support, but the only hotkey is escape
2010-10-20 22:51:19 +11:00
Tim Allen
5286481d8d Update to v070r08 release.
byuu says:

- all three ports of phoenix gain the ability to use
  ListBox::setCheckable(), checked(row), setChecked(row, checked
  = true);
- cheat editor updated to take advantage of this

Some fun differences between the implementations. Windows was the least
flexible, it only lets you have a check at the start of each item.
Luckily that's all I need for my purposes so it'll work. It's also a lot
easier, as now I don't need a ton of extra code to try and set
per-column checkboxes. Now both Windows and Qt can put text into the
first item with the checkbox, but GTK+ cannot. Further, Qt needs this
because even if you hide the checkbox column, it still tries to search
for typed text from the checkbox column. GTK+ does this too, but unlike
GTK+, Qt lacks an API call to set the search column. Since my code
basically has to change this in real-time since you have to call the
setProperty functions after create(), this means I always set up the
checkbox columns regardless of whether or not they are used. For Qt,
I had to work around this and it'll be an annoying edge case if you try
and use setCheckable(true) and then setCheckable(false), because Qt has
no way to clear the checkboxes from an item once you've enabled them for
the first time. But without doing it this way, there's no way for eg the
ROM file loader to allow type-searching, so that's the way I do it.
Windows works the same, and GTK+ has a separate column (hidden from the
phoenix API standpoint) for the checkboxes, with no column header label
text.

All in all, a major hassle, but it was the only really major GUI hit
from leaving Qt, aside from the horror that's going to be the debugger,
which needs all kinds of highly specialized controls.
2010-10-20 22:51:19 +11:00
Tim Allen
440a59c879 Update to v070r07 release.
byuu says:

- added menu options to select controller port devices, they do actually
  work too
- however, input mapping can't map analog axes yet, and the mouse can't
  be captured yet, so it's of little use
- added clear and clear all buttons to the input mapper window, mainly
  because there was no reason not to (escape clears active input too)
- going to be adding a "special" button in the future that lets you map
  mouse axes and buttons
- fixed phoenix/Qt port, both the video rendering and Window::focused()
  commands work now

The way I've implemented mouse mapping has always been screwy. So the
special button is going to pop open another window. For digital mapping,
it'll let you choose a mouse button, and for analog mapping, it'll let
you choose an axis. May add in some manual joypad assignment stuff in
there for analog joypad buttons, those things are impossible to
auto-detect.
2010-10-20 22:51:19 +11:00
Tim Allen
96e9333ec2 Update to v070r06 release.
(there was no r05 release posted to the WIP thread)

byuu says:

- bsnes/phoenix uses XML for per-game cheat codes, markup is identical
  to the main database
- added clear and clear all buttons to the cheat code editor
- phoenix/GTK+ sets all child menu elements to match the parent menu font
- phoenix/Windows will draw a black canvas for the Viewport widget
  (phoenix/GTK+ still needs this)
2010-10-20 22:51:19 +11:00
Tim Allen
775c111fef Update to v070r04 release.
byuu says:

- fixed new config file input driver name (you'll have to delete your old config, or change to a different driver and back and restart)
- fixed slot loader windows' OK button placement
- fixed nall/directory.hpp when list size was zero
- rewrote nall/function.hpp, no longer requires <functional> or union tricks
- added state manager

The state manager is a little bit different this time. It's functionally
identical to bsnes/Qt, 100% of the way. But when you save slots, it
stores them in RAM. It only writes the BSA archive upon ROM unload
/ program exit. Yes, this means that technically if the emulator
crashes, you'll lose your states. But a) that very rarely happens, and
b) the old way was thrashing the disk like crazy, every letter you typed
dumped up to 8MB to disk. With this new method, I can simply store
a boolean valid flag before each slot, and pack the file better. Before,
a save on only slot 3 would be 3*state size (~1.2mb), it will now be
3bytes+state size (~400kb.) I have also added a proper signature because
of this, so it will detect when you load an archive for a previous
serializer version and ignore it. When you go to save (unload the game),
if there are no valid slots, the BSA archive gets unlinked (deleted.)

I am also planning a feature around the now-hidden "slot 0". My idea is
for it to be a fallback slot. How many times have you loaded a state
when you meant to save and said, "shit, now I lost some of my progress"?
The idea is that whenever you load a state, right before loading, it
will save to slot 0. When you unload the game, or exit the emulator, it
will also save to slot 0. You will be able to load from slot 0 from the
menu, but not save to it. It will appear at the bottom of the load list.
And lastly, I'll add an advanced option to auto-load slot 0 if it
exists, which will enable "close the emulator and restart where you left
off." functionality.
2010-10-20 22:51:19 +11:00
Tim Allen
3ffa44cef9 Add pixel shaders from the external tarball.
byuu has traditionally kept these shaders separately, but I don't see
why they shouldn't be stored alongside the code that uses them.

Unlike previous versions of pixel shaders, these are updated to use the
new file-format introduced in v070r03.
2010-10-20 22:51:19 +11:00
Tim Allen
f28d70f9e6 Update to v070r03 release.
byuu says:

- fixed a bug in xml_element::parse() with <![CDATA[...]]> tags
- merged FragmentShader and and VertexShader into Shader, which is an
  XML file that contains all relevant data
- updated Qt port to reflect the above
- added support for pixel shaders to the phoenix port
- updated all pixel shaders to use the new format
- ruby won't crash if you give an HLSL driver a GLSL shader or vice
  versa, but it will still crash on bad programs
- phoenix::Viewport has its own window class, that paints a black brush
  background

[The XML shader] format is subject to change, more specifically I may
change the <source> tag from HLSL shaders.
In the long-long term, it'd be nice to extend the format to allow
multiple shaders to be chained together and to encode base64 texture
files.
But for now, this is good enough.
2010-10-20 22:51:19 +11:00
Tim Allen
73fdbf893f Update to v070r02 release.
byuu says:

- added NTSC/PAL TV output mode selection
- added loading support for BSX Slotted, BSX, Sufami Turbo and Super
  Game Boy games
2010-10-20 22:51:18 +11:00
Tim Allen
da5263bfc3 Update to v070r01 release.
byuu says:

- phoenix supports onActivate, or return key pressed, on text boxes
- phoenix supports setGeometry() on all widgets
- input settings can now map analog axes and analog buttons
- analog button support is simplified over bsnes/Qt, and it supports the
  trigger inversion you see between Xbox 360 and Thrustmaster
  controllers
- load cartridge window lets you press enter in the path box to select
  the folder, but currently allows invalid folders (makes list empty)
- load cartridge won't reset your view if the folder doesn't change
  - this means the last ROM you loaded is highlighted the next time you
    go to load cartridge; you're welcome, FitzRoy :P
- removed quit system menu option
- added dummy controller port system menu options, there's no code
  behind them yet
- added power/reset menu options, dropped the power checkbox in favor of
  a standard power cycle option, removes unnecessary complexity
- added video mode scaling, 1x to 5x; and aspect ratio correction
- added video mode smooth toggle
- added audio settings panel with volume and input frequency adjustment
  - config file is where you can control output frequency and latency,
    they are too niche for a GUI
- fixed a realpath() crash on Linux when the bsnes binary was in /usr/bin
2010-10-20 22:51:18 +11:00
Tim Allen
449a3ad426 Update to v070 release.
byuu says:

This release represents the coup de grâce of bsnes/Qt.

Changelog:
- configuration file is now called bsnes-qt.cfg; the first run of this
  release will start with a clean state
- MSU1 now supports audio looping via new PCM file format
- disabled state load/save menu due to a serious bug in Qt 4.6.0 for
  Windows
- RawInput: all keyboards merged to KB0, it should no longer be required
  to reconfigure the keyboard out-of-the-box
- RawInput: fixed a bug where Xbox 360 controller states were being
  overwritten by DirectInput controllers
- RawInput: fixed a device sorting bug caused by moving ruby to Unicode
- Direct3D: fixed a pixel shader bug caused by moving ruby to Unicode
- Linux port: fixed sudo make install target
- Linux port: default to gcc/g++ instead of gcc-4.5/g++-4.5 for one last
  release
- updated to mightymo's 2010-09-20 cheat pack
2010-10-20 22:51:18 +11:00
180 changed files with 4560 additions and 1725 deletions

View File

@@ -1,7 +1,7 @@
include nall/Makefile include nall/Makefile
snes := snes snes := snes
profile := compatibility profile := accuracy
ui := ui-qt ui := ui-phoenix
# compiler # compiler
c := $(compiler) -std=gnu99 c := $(compiler) -std=gnu99
@@ -62,9 +62,11 @@ endif
install: install:
ifeq ($(platform),x) ifeq ($(platform),x)
install -D -m 755 out/bsnes $(DESTDIR)$(prefix)/bin/bsnes install -D -m 755 out/bsnes $(DESTDIR)$(prefix)/bin/bsnes
install -D -m 644 qt/data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
install -D -m 644 qt/data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
gconftool-2 --type bool --set /desktop/gnome/interface/menus_have_icons true test -d ~/.bsnes || mkdir ~/.bsnes
cp data/cheats.xml ~/.bsnes/cheats.xml
chmod 777 ~/.bsnes ~/.bsnes/cheats.xml
endif endif
uninstall: uninstall:
@@ -88,6 +90,6 @@ clean: ui_clean
-@$(call delete,*.manifest) -@$(call delete,*.manifest)
archive-all: archive-all:
tar -cjf bsnes.tar.bz2 launcher libco nall obj out phoenix ruby snes ui-phoenix ui-qt Makefile cc.bat clean.bat sync.sh tar -cjf bsnes.tar.bz2 data launcher libco nall obj out phoenix ruby snes ui-phoenix ui-qt Makefile cc.bat clean.bat sync.sh
help:; help:;

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="bsnes" version="1.0.0.0" processorArchitecture="x86"/> <assemblyIdentity type="win32" name="bsnes" version="1.0.0.0" processorArchitecture="*"/>
<dependency> <dependency>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*"/> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly> </dependentAssembly>
</dependency> </dependency>
</assembly> </assembly>

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -16,10 +16,10 @@ int main(int argc, char **argv) {
unused = realpath(nall::utf8_t(argw[0]), path); unused = realpath(nall::utf8_t(argw[0]), path);
#endif #endif
string realPath = dir(path); string realPath = dir(path);
string basePath = string(dir(path), "bsnes.cfg"); string basePath = string(dir(path), "bsnes-qt.cfg");
unused = userpath(path); unused = userpath(path);
if(!strend(path, "/") && !strend(path, "\\")) strcat(path, "/"); if(!strend(path, "/") && !strend(path, "\\")) strcat(path, "/");
string userPath = string(path, ".bsnes/bsnes.cfg"); string userPath = string(path, ".bsnes/bsnes-qt.cfg");
configuration config; configuration config;
string profile; string profile;

View File

@@ -102,7 +102,7 @@ namespace nall {
virtual bool save(const char *filename) const { virtual bool save(const char *filename) const {
file fp; file fp;
if(fp.open(filename, file::mode_write)) { if(fp.open(filename, file::mode::write)) {
for(unsigned i = 0; i < list.size(); i++) { for(unsigned i = 0; i < list.size(); i++) {
string output; string output;
output << list[i].name << " = " << list[i].get(); output << list[i].name << " = " << list[i].get();

View File

@@ -27,7 +27,7 @@ namespace nall {
bool import(const char *filename) { bool import(const char *filename) {
string data; string data;
if(data.readfile(filename) == false) return false; if(data.readfile(filename) == false) return false;
data.ltrim_once("\xef\xbb\xbf"); //remove UTF-8 marker, if it exists data.ltrim<1>("\xef\xbb\xbf"); //remove UTF-8 marker, if it exists
data.replace("\r", ""); data.replace("\r", "");
lstring line; lstring line;
@@ -43,8 +43,8 @@ namespace nall {
part[1].trim(); part[1].trim();
//remove quotes //remove quotes
part[0].trim_once("\""); part[0].trim<1>("\"");
part[1].trim_once("\""); part[1].trim<1>("\"");
unsigned n = index_input.size(); unsigned n = index_input.size();
index_input[n] = part[0]; index_input[n] = part[0];

View File

@@ -16,13 +16,13 @@
namespace nall { namespace nall {
struct directory { struct directory {
static lstring folders(const char *pathname); static lstring folders(const string &pathname, const string &pattern = "*");
static lstring files(const char *pathname); static lstring files(const string &pathname, const string &pattern = "*");
static lstring contents(const char *pathname); static lstring contents(const string &pathname, const string &pattern = "*");
}; };
#if defined(_WIN32) #if defined(_WIN32)
inline lstring directory::folders(const char *pathname) { inline lstring directory::folders(const string &pathname, const string &pattern) {
lstring list; lstring list;
string path = pathname; string path = pathname;
path.transform("/", "\\"); path.transform("/", "\\");
@@ -34,23 +34,25 @@ struct directory {
if(handle != INVALID_HANDLE_VALUE) { if(handle != INVALID_HANDLE_VALUE) {
if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
list.append(string(utf8_t(data.cFileName), "/")); string name = utf8_t(data.cFileName);
if(wildcard(name, pattern)) list.append(string(name, "/"));
} }
} }
while(FindNextFile(handle, &data) != false) { while(FindNextFile(handle, &data) != false) {
if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
list.append(string(utf8_t(data.cFileName), "/")); string name = utf8_t(data.cFileName);
if(wildcard(name, pattern)) list.append(string(name, "/"));
} }
} }
} }
FindClose(handle); FindClose(handle);
} }
sort(&list[0], list.size()); if(list.size() > 0) sort(&list[0], list.size());
return list; return list;
} }
inline lstring directory::files(const char *pathname) { inline lstring directory::files(const string &pathname, const string &pattern) {
lstring list; lstring list;
string path = pathname; string path = pathname;
path.transform("/", "\\"); path.transform("/", "\\");
@@ -61,27 +63,29 @@ struct directory {
handle = FindFirstFile(utf16_t(path), &data); handle = FindFirstFile(utf16_t(path), &data);
if(handle != INVALID_HANDLE_VALUE) { if(handle != INVALID_HANDLE_VALUE) {
if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
list.append(utf8_t(data.cFileName)); string name = utf8_t(data.cFileName);
if(wildcard(name, pattern)) list.append(name);
} }
while(FindNextFile(handle, &data) != false) { while(FindNextFile(handle, &data) != false) {
if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
list.append(utf8_t(data.cFileName)); string name = utf8_t(data.cFileName);
if(wildcard(name, pattern)) list.append(name);
} }
} }
FindClose(handle); FindClose(handle);
} }
sort(&list[0], list.size()); if(list.size() > 0) sort(&list[0], list.size());
return list; return list;
} }
inline lstring directory::contents(const char *pathname) { inline lstring directory::contents(const string &pathname, const string &pattern) {
lstring folders = directory::folders(pathname); lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files
lstring files = directory::files(pathname); lstring files = directory::files(pathname, pattern);
foreach(file, files) folders.append(file); foreach(file, files) folders.append(file);
return folders; return folders;
} }
#else #else
inline lstring directory::folders(const char *pathname) { inline lstring directory::folders(const string &pathname, const string &pattern) {
lstring list; lstring list;
DIR *dp; DIR *dp;
struct dirent *ep; struct dirent *ep;
@@ -90,16 +94,18 @@ struct directory {
while(ep = readdir(dp)) { while(ep = readdir(dp)) {
if(!strcmp(ep->d_name, ".")) continue; if(!strcmp(ep->d_name, ".")) continue;
if(!strcmp(ep->d_name, "..")) continue; if(!strcmp(ep->d_name, "..")) continue;
if(ep->d_type & DT_DIR) list.append(string(ep->d_name, "/")); if(ep->d_type & DT_DIR) {
if(wildcard(ep->d_name, pattern)) list.append(string(ep->d_name, "/"));
}
} }
closedir(dp); closedir(dp);
} }
sort(&list[0], list.size()); if(list.size() > 0) sort(&list[0], list.size());
return list; return list;
} }
inline lstring directory::files(const char *pathname) { inline lstring directory::files(const string &pathname, const string &pattern) {
lstring list; lstring list;
DIR *dp; DIR *dp;
struct dirent *ep; struct dirent *ep;
@@ -108,17 +114,19 @@ struct directory {
while(ep = readdir(dp)) { while(ep = readdir(dp)) {
if(!strcmp(ep->d_name, ".")) continue; if(!strcmp(ep->d_name, ".")) continue;
if(!strcmp(ep->d_name, "..")) continue; if(!strcmp(ep->d_name, "..")) continue;
if((ep->d_type & DT_DIR) == 0) list.append(ep->d_name); if((ep->d_type & DT_DIR) == 0) {
if(wildcard(ep->d_name, pattern)) list.append(ep->d_name);
}
} }
closedir(dp); closedir(dp);
} }
sort(&list[0], list.size()); if(list.size() > 0) sort(&list[0], list.size());
return list; return list;
} }
inline lstring directory::contents(const char *pathname) { inline lstring directory::contents(const string &pathname, const string &pattern) {
lstring folders = directory::folders(pathname); lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files
lstring files = directory::files(pathname); lstring files = directory::files(pathname, pattern);
foreach(file, files) folders.append(file); foreach(file, files) folders.append(file);
return folders; return folders;
} }

View File

@@ -26,12 +26,12 @@ namespace nall {
class file { class file {
public: public:
enum FileMode { mode_read, mode_write, mode_readwrite, mode_writeread }; enum class mode : unsigned { read, write, readwrite, writeread };
enum SeekMode { seek_absolute, seek_relative }; enum class index : unsigned { absolute, relative };
uint8_t read() { uint8_t read() {
if(!fp) return 0xff; //file not open if(!fp) return 0xff; //file not open
if(file_mode == mode_write) return 0xff; //reads not permitted if(file_mode == mode::write) return 0xff; //reads not permitted
if(file_offset >= file_size) return 0xff; //cannot read past end of file if(file_offset >= file_size) return 0xff; //cannot read past end of file
buffer_sync(); buffer_sync();
return buffer[(file_offset++) & buffer_mask]; return buffer[(file_offset++) & buffer_mask];
@@ -60,7 +60,7 @@ namespace nall {
void write(uint8_t data) { void write(uint8_t data) {
if(!fp) return; //file not open if(!fp) return; //file not open
if(file_mode == mode_read) return; //writes not permitted if(file_mode == mode::read) return; //writes not permitted
buffer_sync(); buffer_sync();
buffer[(file_offset++) & buffer_mask] = data; buffer[(file_offset++) & buffer_mask] = data;
buffer_dirty = true; buffer_dirty = true;
@@ -95,19 +95,19 @@ namespace nall {
fflush(fp); fflush(fp);
} }
void seek(int offset, SeekMode mode = seek_absolute) { void seek(int offset, index index_ = index::absolute) {
if(!fp) return; //file not open if(!fp) return; //file not open
buffer_flush(); buffer_flush();
uintmax_t req_offset = file_offset; uintmax_t req_offset = file_offset;
switch(mode) { switch(index_) {
case seek_absolute: req_offset = offset; break; case index::absolute: req_offset = offset; break;
case seek_relative: req_offset += offset; break; case index::relative: req_offset += offset; break;
} }
if(req_offset < 0) req_offset = 0; //cannot seek before start of file if(req_offset < 0) req_offset = 0; //cannot seek before start of file
if(req_offset > file_size) { if(req_offset > file_size) {
if(file_mode == mode_read) { //cannot seek past end of file if(file_mode == mode::read) { //cannot seek past end of file
req_offset = file_size; req_offset = file_size;
} else { //pad file to requested location } else { //pad file to requested location
file_offset = file_size; file_offset = file_size;
@@ -174,20 +174,20 @@ namespace nall {
return fp; return fp;
} }
bool open(const char *fn, FileMode mode) { bool open(const char *fn, mode mode_) {
if(fp) return false; if(fp) return false;
switch(file_mode = mode) { switch(file_mode = mode_) {
#if !defined(_WIN32) #if !defined(_WIN32)
case mode_read: fp = fopen(fn, "rb"); break; case mode::read: fp = fopen(fn, "rb"); break;
case mode_write: fp = fopen(fn, "wb+"); break; //need read permission for buffering case mode::write: fp = fopen(fn, "wb+"); break; //need read permission for buffering
case mode_readwrite: fp = fopen(fn, "rb+"); break; case mode::readwrite: fp = fopen(fn, "rb+"); break;
case mode_writeread: fp = fopen(fn, "wb+"); break; case mode::writeread: fp = fopen(fn, "wb+"); break;
#else #else
case mode_read: fp = _wfopen(utf16_t(fn), L"rb"); break; case mode::read: fp = _wfopen(utf16_t(fn), L"rb"); break;
case mode_write: fp = _wfopen(utf16_t(fn), L"wb+"); break; case mode::write: fp = _wfopen(utf16_t(fn), L"wb+"); break;
case mode_readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break; case mode::readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break;
case mode_writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break; case mode::writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break;
#endif #endif
} }
if(!fp) return false; if(!fp) return false;
@@ -213,7 +213,7 @@ namespace nall {
fp = 0; fp = 0;
file_offset = 0; file_offset = 0;
file_size = 0; file_size = 0;
file_mode = mode_read; file_mode = mode::read;
} }
~file() { ~file() {
@@ -231,7 +231,7 @@ namespace nall {
FILE *fp; FILE *fp;
unsigned file_offset; unsigned file_offset;
unsigned file_size; unsigned file_size;
FileMode file_mode; mode file_mode;
void buffer_sync() { void buffer_sync() {
if(!fp) return; //file not open if(!fp) return; //file not open
@@ -246,7 +246,7 @@ namespace nall {
void buffer_flush() { void buffer_flush() {
if(!fp) return; //file not open if(!fp) return; //file not open
if(file_mode == mode_read) return; //buffer cannot be written to if(file_mode == mode::read) return; //buffer cannot be written to
if(buffer_offset < 0) return; //buffer unused if(buffer_offset < 0) return; //buffer unused
if(buffer_dirty == false) return; //buffer unmodified since read if(buffer_dirty == false) return; //buffer unmodified since read
fseek(fp, buffer_offset, SEEK_SET); fseek(fp, buffer_offset, SEEK_SET);

View File

@@ -19,14 +19,16 @@
namespace nall { namespace nall {
class filemap { class filemap {
public: public:
enum filemode { mode_read, mode_write, mode_readwrite, mode_writeread }; enum class mode : unsigned { read, write, readwrite, writeread };
bool open(const char *filename, filemode mode) { return p_open(filename, mode); } bool opened() const { return p_opened(); }
bool open(const char *filename, mode mode_) { return p_open(filename, mode_); }
void close() { return p_close(); } void close() { return p_close(); }
unsigned size() const { return p_size; } unsigned size() const { return p_size; }
uint8_t* handle() { return p_handle; } uint8_t* data() { return p_handle; }
const uint8_t* handle() const { return p_handle; } const uint8_t* data() const { return p_handle; }
filemap() : p_size(0), p_handle(0) { p_ctor(); } filemap() : p_size(0), p_handle(0) { p_ctor(); }
filemap(const char *filename, mode mode_) : p_size(0), p_handle(0) { p_ctor(); p_open(filename, mode_); }
~filemap() { p_dtor(); } ~filemap() { p_dtor(); }
private: private:
@@ -40,31 +42,35 @@ namespace nall {
HANDLE p_filehandle, p_maphandle; HANDLE p_filehandle, p_maphandle;
bool p_open(const char *filename, filemode mode) { bool p_opened() const {
return p_handle;
}
bool p_open(const char *filename, mode mode_) {
int desired_access, creation_disposition, flprotect, map_access; int desired_access, creation_disposition, flprotect, map_access;
switch(mode) { switch(mode_) {
default: return false; default: return false;
case mode_read: case mode::read:
desired_access = GENERIC_READ; desired_access = GENERIC_READ;
creation_disposition = OPEN_EXISTING; creation_disposition = OPEN_EXISTING;
flprotect = PAGE_READONLY; flprotect = PAGE_READONLY;
map_access = FILE_MAP_READ; map_access = FILE_MAP_READ;
break; break;
case mode_write: case mode::write:
//write access requires read access //write access requires read access
desired_access = GENERIC_WRITE; desired_access = GENERIC_WRITE;
creation_disposition = CREATE_ALWAYS; creation_disposition = CREATE_ALWAYS;
flprotect = PAGE_READWRITE; flprotect = PAGE_READWRITE;
map_access = FILE_MAP_ALL_ACCESS; map_access = FILE_MAP_ALL_ACCESS;
break; break;
case mode_readwrite: case mode::readwrite:
desired_access = GENERIC_READ | GENERIC_WRITE; desired_access = GENERIC_READ | GENERIC_WRITE;
creation_disposition = OPEN_EXISTING; creation_disposition = OPEN_EXISTING;
flprotect = PAGE_READWRITE; flprotect = PAGE_READWRITE;
map_access = FILE_MAP_ALL_ACCESS; map_access = FILE_MAP_ALL_ACCESS;
break; break;
case mode_writeread: case mode::writeread:
desired_access = GENERIC_READ | GENERIC_WRITE; desired_access = GENERIC_READ | GENERIC_WRITE;
creation_disposition = CREATE_NEW; creation_disposition = CREATE_NEW;
flprotect = PAGE_READWRITE; flprotect = PAGE_READWRITE;
@@ -122,30 +128,34 @@ namespace nall {
int p_fd; int p_fd;
bool p_open(const char *filename, filemode mode) { bool p_opened() const {
return p_handle;
}
bool p_open(const char *filename, mode mode_) {
int open_flags, mmap_flags; int open_flags, mmap_flags;
switch(mode) { switch(mode_) {
default: return false; default: return false;
case mode_read: case mode::read:
open_flags = O_RDONLY; open_flags = O_RDONLY;
mmap_flags = PROT_READ; mmap_flags = PROT_READ;
break; break;
case mode_write: case mode::write:
open_flags = O_RDWR | O_CREAT; //mmap() requires read access open_flags = O_RDWR | O_CREAT; //mmap() requires read access
mmap_flags = PROT_WRITE; mmap_flags = PROT_WRITE;
break; break;
case mode_readwrite: case mode::readwrite:
open_flags = O_RDWR; open_flags = O_RDWR;
mmap_flags = PROT_READ | PROT_WRITE; mmap_flags = PROT_READ | PROT_WRITE;
break; break;
case mode_writeread: case mode::writeread:
open_flags = O_RDWR | O_CREAT; open_flags = O_RDWR | O_CREAT;
mmap_flags = PROT_READ | PROT_WRITE; mmap_flags = PROT_READ | PROT_WRITE;
break; break;
} }
p_fd = ::open(filename, open_flags); p_fd = ::open(filename, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if(p_fd < 0) return false; if(p_fd < 0) return false;
struct stat p_stat; struct stat p_stat;

View File

@@ -1,90 +1,59 @@
#ifndef NALL_FUNCTION_HPP #ifndef NALL_FUNCTION_HPP
#define NALL_FUNCTION_HPP #define NALL_FUNCTION_HPP
#include <stdlib.h>
#include <functional>
#include <type_traits>
namespace nall { namespace nall {
template<typename T> class function; template<typename T> class function;
template<typename R, typename... P> template<typename R, typename... P> class function<R (P...)> {
class function<R (P...)> { struct container {
private: virtual R operator()(P... p) const = 0;
struct base1 { virtual void func1(P...) {} }; virtual container* copy() const = 0;
struct base2 { virtual void func2(P...) {} }; virtual ~container() {}
struct derived : base1, virtual base2 {}; } *callback;
struct data_t { struct global : container {
R (*callback)(const data_t&, P...); R (*function)(P...);
union { R operator()(P... p) const { return function(std::forward<P>(p)...); }
R (*callback_global)(P...); container* copy() const { return new global(function); }
struct { global(R (*function)(P...)) : function(function) {}
R (derived::*callback_member)(P...);
void *object;
}; };
template<typename C> struct member : container {
R (C::*function)(P...);
C *object;
R operator()(P... p) const { return (object->*function)(std::forward<P>(p)...); }
container* copy() const { return new member(function, object); }
member(R (C::*function)(P...), C *object) : function(function), object(object) {}
}; };
} data;
static R callback_global(const data_t &data, P... p) { template<typename L> struct lambda : container {
return data.callback_global(p...); L object;
} R operator()(P... p) const { return object(std::forward<P>(p)...); }
container* copy() const { return new lambda(object); }
template<typename C> lambda(const L& object) : object(object) {}
static R callback_member(const data_t &data, P... p) { };
return (((C*)data.object)->*((R (C::*&)(P...))data.callback_member))(p...);
}
public: public:
R operator()(P... p) const { return data.callback(data, p...); } operator bool() const { return callback; }
operator bool() const { return data.callback; } R operator()(P... p) const { return (*callback)(std::forward<P>(p)...); }
void reset() { data.callback = 0; } void reset() { if(callback) { delete callback; callback = 0; } }
function& operator=(const function &source) {
if(this != &source) {
if(callback) { delete callback; callback = 0; }
if(source.callback) callback = source.callback->copy();
}
return *this;
}
function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
function(const function &source) { operator=(source); } function(const function &source) { operator=(source); }
function() : callback(0) {}
//no pointer function(void *function) : callback(0) { if(function) callback = new global((R (*)(P...))function); }
function() { function(R (*function)(P...)) { callback = new global(function); }
data.callback = 0; template<typename C> function(R (C::*function)(P...), C *object) { callback = new member<C>(function, object); }
} template<typename C> function(R (C::*function)(P...) const, C *object) { callback = new member<C>((R (C::*)(P...))function, object); }
template<typename L> function(const L& object) { callback = new lambda<L>(object); }
//symbolic link pointer (nall/dl.hpp::sym, etc) ~function() { if(callback) delete callback; }
function(void *callback) {
data.callback = callback ? &callback_global : 0;
data.callback_global = (R (*)(P...))callback;
}
//global function pointer
function(R (*callback)(P...)) {
data.callback = &callback_global;
data.callback_global = callback;
}
//member function pointer
template<typename C>
function(R (C::*callback)(P...), C *object) {
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
data.callback = &callback_member<C>;
(R (C::*&)(P...))data.callback_member = callback;
data.object = object;
}
//const member function pointer
template<typename C>
function(R (C::*callback)(P...) const, C *object) {
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
data.callback = &callback_member<C>;
(R (C::*&)(P...))data.callback_member = (R (C::*&)(P...))callback;
data.object = object;
}
//lambda function pointer
template<typename T>
function(T callback) {
static_assert(std::is_same<R, typename std::result_of<T(P...)>::type>::value, "lambda mismatch");
data.callback = &callback_global;
data.callback_global = (R (*)(P...))callback;
}
}; };
} }

View File

@@ -112,6 +112,7 @@ namespace nall {
imode = Size; imode = Size;
idata = 0; idata = 0;
isize = 0; isize = 0;
icapacity = 0;
} }
serializer(unsigned capacity) { serializer(unsigned capacity) {

View File

@@ -9,7 +9,7 @@ public:
inline snes_information(const uint8_t *data, unsigned size); inline snes_information(const uint8_t *data, unsigned size);
private: //private:
inline void read_header(const uint8_t *data, unsigned size); inline void read_header(const uint8_t *data, unsigned size);
inline unsigned find_header(const uint8_t *data, unsigned size); inline unsigned find_header(const uint8_t *data, unsigned size);
inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr); inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);

View File

@@ -2,6 +2,7 @@
#define NALL_STRING_HPP #define NALL_STRING_HPP
#include <initializer_list> #include <initializer_list>
#include <nall/platform.hpp>
#include <nall/utility.hpp> #include <nall/utility.hpp>
#include <nall/string/base.hpp> #include <nall/string/base.hpp>
@@ -13,6 +14,7 @@
#include <nall/string/filename.hpp> #include <nall/string/filename.hpp>
#include <nall/string/match.hpp> #include <nall/string/match.hpp>
#include <nall/string/math.hpp> #include <nall/string/math.hpp>
#include <nall/string/platform.hpp>
#include <nall/string/strl.hpp> #include <nall/string/strl.hpp>
#include <nall/string/strpos.hpp> #include <nall/string/strpos.hpp>
#include <nall/string/trim.hpp> #include <nall/string/trim.hpp>
@@ -20,6 +22,7 @@
#include <nall/string/split.hpp> #include <nall/string/split.hpp>
#include <nall/string/utility.hpp> #include <nall/string/utility.hpp>
#include <nall/string/variadic.hpp> #include <nall/string/variadic.hpp>
#include <nall/string/wrapper.hpp>
#include <nall/string/xml.hpp> #include <nall/string/xml.hpp>
namespace nall { namespace nall {

View File

@@ -17,7 +17,6 @@ namespace nall {
class string { class string {
public: public:
inline void reserve(unsigned); inline void reserve(unsigned);
inline unsigned length() const;
inline string& assign(const char*); inline string& assign(const char*);
inline string& append(const char*); inline string& append(const char*);
@@ -26,6 +25,35 @@ namespace nall {
inline string& append(unsigned int value); inline string& append(unsigned int value);
inline string& append(double value); inline string& append(double value);
inline bool readfile(const char*);
inline string& replace (const char*, const char*);
inline string& qreplace(const char*, const char*);
inline unsigned length() const;
inline bool equals(const char*) const;
inline bool iequals(const char*) const;
inline bool wildcard(const char*) const;
inline bool iwildcard(const char*) const;
inline bool beginswith(const char*) const;
inline bool ibeginswith(const char*) const;
inline bool endswith(const char*) const;
inline bool iendswith(const char*) const;
inline string& lower();
inline string& upper();
inline string& transform(const char *before, const char *after);
template<unsigned limit = 0> inline string& ltrim(const char *key = " ");
template<unsigned limit = 0> inline string& rtrim(const char *key = " ");
template<unsigned limit = 0> inline string& trim (const char *key = " ");
inline optional<unsigned> position(const char *key) const;
inline optional<unsigned> qposition(const char *key) const;
template<typename T> inline string& operator= (T value); template<typename T> inline string& operator= (T value);
template<typename T> inline string& operator<<(T value); template<typename T> inline string& operator<<(T value);
@@ -48,20 +76,6 @@ namespace nall {
inline string(string&&); inline string(string&&);
inline ~string(); inline ~string();
inline bool readfile(const char*);
inline string& replace (const char*, const char*);
inline string& qreplace(const char*, const char*);
inline string& lower();
inline string& upper();
inline string& transform(const char *before, const char *after);
inline string& ltrim(const char *key = " ");
inline string& rtrim(const char *key = " ");
inline string& trim (const char *key = " ");
inline string& ltrim_once(const char *key = " ");
inline string& rtrim_once(const char *key = " ");
inline string& trim_once (const char *key = " ");
protected: protected:
char *data; char *data;
unsigned size; unsigned size;
@@ -76,9 +90,9 @@ namespace nall {
public: public:
template<typename T> inline lstring& operator<<(T value); template<typename T> inline lstring& operator<<(T value);
inline optional<unsigned> find(const char*); inline optional<unsigned> find(const char*) const;
inline void split (const char*, const char*, unsigned = 0); template<unsigned limit = 0> inline void split (const char*, const char*);
inline void qsplit(const char*, const char*, unsigned = 0); template<unsigned limit = 0> inline void qsplit(const char*, const char*);
lstring(); lstring();
lstring(std::initializer_list<string>); lstring(std::initializer_list<string>);
@@ -87,7 +101,9 @@ namespace nall {
//compare.hpp //compare.hpp
inline char chrlower(char c); inline char chrlower(char c);
inline char chrupper(char c); inline char chrupper(char c);
inline int stricmp(const char *dest, const char *src); inline int stricmp(const char *str1, const char *str2);
inline bool wildcard(const char *str, const char *pattern);
inline bool iwildcard(const char *str, const char *pattern);
inline bool strbegin (const char *str, const char *key); inline bool strbegin (const char *str, const char *key);
inline bool stribegin(const char *str, const char *key); inline bool stribegin(const char *str, const char *key);
inline bool strend (const char *str, const char *key); inline bool strend (const char *str, const char *key);
@@ -110,23 +126,28 @@ namespace nall {
inline bool strint (const char *str, int &result); inline bool strint (const char *str, int &result);
inline bool strmath(const char *str, int &result); inline bool strmath(const char *str, int &result);
//platform.hpp
inline string realpath(const char *name);
inline string userpath();
inline string currentpath();
//strl.hpp //strl.hpp
inline unsigned strlcpy(char *dest, const char *src, unsigned length); inline unsigned strlcpy(char *dest, const char *src, unsigned length);
inline unsigned strlcat(char *dest, const char *src, unsigned length); inline unsigned strlcat(char *dest, const char *src, unsigned length);
//strpos.hpp
inline optional<unsigned> strpos(const char *str, const char *key);
inline optional<unsigned> qstrpos(const char *str, const char *key);
//trim.hpp //trim.hpp
inline char* ltrim(char *str, const char *key = " "); template<unsigned limit = 0> inline char* ltrim(char *str, const char *key = " ");
inline char* rtrim(char *str, const char *key = " "); template<unsigned limit = 0> inline char* rtrim(char *str, const char *key = " ");
inline char* trim (char *str, const char *key = " "); template<unsigned limit = 0> inline char* trim (char *str, const char *key = " ");
inline char* ltrim_once(char *str, const char *key = " ");
inline char* rtrim_once(char *str, const char *key = " ");
inline char* trim_once (char *str, const char *key = " ");
//utility.hpp //utility.hpp
inline unsigned strlcpy(string &dest, const char *src, unsigned length); inline unsigned strlcpy(string &dest, const char *src, unsigned length);
inline unsigned strlcat(string &dest, const char *src, unsigned length); inline unsigned strlcat(string &dest, const char *src, unsigned length);
inline string substr(const char *src, unsigned start = 0, unsigned length = 0); inline string substr(const char *src, unsigned start = 0, unsigned length = 0);
inline string& strtr(string &dest, const char *before, const char *after);
template<unsigned length = 0, char padding = '0'> inline string strhex(uintmax_t value); template<unsigned length = 0, char padding = '0'> inline string strhex(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strsigned(intmax_t value); template<unsigned length = 0, char padding = '0'> inline string strsigned(intmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strunsigned(uintmax_t value); template<unsigned length = 0, char padding = '0'> inline string strunsigned(uintmax_t value);

View File

@@ -11,14 +11,52 @@ char chrupper(char c) {
return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
} }
int stricmp(const char *dest, const char *src) { int stricmp(const char *str1, const char *str2) {
while(*dest) { while(*str1) {
if(chrlower(*dest) != chrlower(*src)) break; if(chrlower(*str1) != chrlower(*str2)) break;
dest++; str1++, str2++;
src++; }
return (int)chrlower(*str1) - (int)chrlower(*str2);
} }
return (int)chrlower(*dest) - (int)chrlower(*src); bool wildcard(const char *s, const char *p) {
const char *cp = 0, *mp = 0;
while(*s && *p != '*') {
if(*p != '?' && *s != *p) return false;
p++, s++;
}
while(*s) {
if(*p == '*') {
if(!*++p) return true;
mp = p, cp = s + 1;
} else if(*p == '?' || *p == *s) {
p++, s++;
} else {
p = mp, s = cp++;
}
}
while(*p == '*') p++;
return !*p;
}
bool iwildcard(const char *s, const char *p) {
const char *cp = 0, *mp = 0;
while(*s && *p != '*') {
if(*p != '?' && chrlower(*s) != chrlower(*p)) return false;
p++, s++;
}
while(*s) {
if(*p == '*') {
if(!*++p) return true;
mp = p, cp = s + 1;
} else if(*p == '?' || chrlower(*p) == chrlower(*s)) {
p++, s++;
} else {
p = mp, s = cp++;
}
}
while(*p == '*') p++;
return !*p;
} }
bool strbegin(const char *str, const char *key) { bool strbegin(const char *str, const char *key) {

View File

@@ -40,10 +40,6 @@ char* strtr(char *dest, const char *before, const char *after) {
return dest; return dest;
} }
string& string::lower() { nall::strlower(data); return *this; }
string& string::upper() { nall::strupper(data); return *this; }
string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; }
uintmax_t strhex(const char *str) { uintmax_t strhex(const char *str) {
if(!str) return 0; if(!str) return 0;
uintmax_t result = 0; uintmax_t result = 0;

View File

@@ -11,10 +11,6 @@ void string::reserve(unsigned size_) {
} }
} }
unsigned string::length() const {
return strlen(data);
}
string& string::assign(const char *s) { string& string::assign(const char *s) {
unsigned length = strlen(s); unsigned length = strlen(s);
reserve(length); reserve(length);
@@ -122,7 +118,7 @@ bool string::readfile(const char *filename) {
return true; return true;
} }
optional<unsigned> lstring::find(const char *key) { optional<unsigned> lstring::find(const char *key) const {
for(unsigned i = 0; i < size(); i++) { for(unsigned i = 0; i < size(); i++) {
if(operator[](i) == key) return { true, i }; if(operator[](i) == key) return { true, i };
} }

View File

@@ -3,7 +3,9 @@
namespace nall { namespace nall {
// "foo/bar.c" -> "foo/", "bar.c" -> "./" // "foo/bar.c" -> "foo/"
// "foo/" -> "foo/"
// "bar.c" -> "./"
inline string dir(char const *name) { inline string dir(char const *name) {
string result = name; string result = name;
for(signed i = strlen(result); i >= 0; i--) { for(signed i = strlen(result); i >= 0; i--) {

41
bsnes/nall/string/platform.hpp Executable file
View File

@@ -0,0 +1,41 @@
#ifndef NALL_STRING_PLATFORM_HPP
#define NALL_STRING_PLATFORM_HPP
namespace nall {
string realpath(const char *name) {
char path[PATH_MAX];
if(::realpath(name, path)) {
string result(path);
result.transform("\\", "/");
if(result.endswith("/") == false) result.append("/");
return result;
}
return "";
}
string userpath() {
char path[PATH_MAX];
if(::userpath(path)) {
string result(path);
result.transform("\\", "/");
if(result.endswith("/") == false) result.append("/");
return result;
}
return "";
}
string currentpath() {
char path[PATH_MAX];
if(::getcwd(path)) {
string result(path);
result.transform("\\", "/");
if(result.endswith("/") == false) result.append("/");
return result;
}
return "";
}
}
#endif

View File

@@ -3,7 +3,8 @@
namespace nall { namespace nall {
void lstring::split(const char *key, const char *src, unsigned limit) { template<unsigned Limit> void lstring::split(const char *key, const char *src) {
unsigned limit = Limit;
reset(); reset();
int ssl = strlen(src), ksl = strlen(key); int ssl = strlen(src), ksl = strlen(key);
@@ -21,7 +22,8 @@ void lstring::split(const char *key, const char *src, unsigned limit) {
operator[](split_count++) = src + lp; operator[](split_count++) = src + lp;
} }
void lstring::qsplit(const char *key, const char *src, unsigned limit) { template<unsigned Limit> void lstring::qsplit(const char *key, const char *src) {
unsigned limit = Limit;
reset(); reset();
int ssl = strlen(src), ksl = strlen(key); int ssl = strlen(src), ksl = strlen(key);

View File

@@ -7,7 +7,7 @@
namespace nall { namespace nall {
inline optional<unsigned> strpos(const char *str, const char *key) { optional<unsigned> strpos(const char *str, const char *key) {
unsigned ssl = strlen(str), ksl = strlen(key); unsigned ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl) return { false, 0 }; if(ksl > ssl) return { false, 0 };
@@ -18,7 +18,7 @@ inline optional<unsigned> strpos(const char *str, const char *key) {
return { false, 0 }; return { false, 0 };
} }
inline optional<unsigned> qstrpos(const char *str, const char *key) { optional<unsigned> qstrpos(const char *str, const char *key) {
unsigned ssl = strlen(str), ksl = strlen(key); unsigned ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl) return { false, 0 }; if(ksl > ssl) return { false, 0 };

View File

@@ -3,7 +3,9 @@
namespace nall { namespace nall {
char* ltrim(char *str, const char *key) { //limit defaults to zero, which will underflow on first compare; equivalent to no limit
template<unsigned Limit> char* ltrim(char *str, const char *key) {
unsigned limit = Limit;
if(!key || !*key) return str; if(!key || !*key) return str;
while(strbegin(str, key)) { while(strbegin(str, key)) {
char *dest = str, *src = str + strlen(key); char *dest = str, *src = str + strlen(key);
@@ -12,50 +14,25 @@ char* ltrim(char *str, const char *key) {
if(!*dest) break; if(!*dest) break;
dest++; dest++;
} }
if(--limit == 0) break;
} }
return str; return str;
} }
char* rtrim(char *str, const char *key) { template<unsigned Limit> char* rtrim(char *str, const char *key) {
unsigned limit = Limit;
if(!key || !*key) return str; if(!key || !*key) return str;
while(strend(str, key)) str[strlen(str) - strlen(key)] = 0; while(strend(str, key)) {
return str; str[strlen(str) - strlen(key)] = 0;
} if(--limit == 0) break;
char* trim(char *str, const char *key) {
return ltrim(rtrim(str, key), key);
}
char* ltrim_once(char *str, const char *key) {
if(!key || !*key) return str;
if(strbegin(str, key)) {
char *dest = str, *src = str + strlen(key);
while(true) {
*dest = *src++;
if(!*dest) break;
dest++;
}
} }
return str; return str;
} }
char* rtrim_once(char *str, const char *key) { template<unsigned limit> char* trim(char *str, const char *key) {
if(!key || !*key) return str; return ltrim<limit>(rtrim<limit>(str, key), key);
if(strend(str, key)) str[strlen(str) - strlen(key)] = 0;
return str;
} }
char* trim_once(char *str, const char *key) {
return ltrim_once(rtrim_once(str, key), key);
}
string& string::ltrim(const char *key) { nall::ltrim(data, key); return *this; }
string& string::rtrim(const char *key) { nall::rtrim(data, key); return *this; }
string& string::trim (const char *key) { nall::trim (data, key); return *this; }
string& string::ltrim_once(const char *key) { nall::ltrim_once(data, key); return *this; }
string& string::rtrim_once(const char *key) { nall::rtrim_once(data, key); return *this; }
string& string::trim_once (const char *key) { nall::trim_once (data, key); return *this; }
} }
#endif #endif

33
bsnes/nall/string/wrapper.hpp Executable file
View File

@@ -0,0 +1,33 @@
#ifndef NALL_STRING_WRAPPER_HPP
#define NALL_STRING_WRAPPER_HPP
namespace nall {
unsigned string::length() const { return strlen(data); }
bool string::equals(const char *str) const { return !strcmp(data, str); }
bool string::iequals(const char *str) const { return !stricmp(data, str); }
bool string::wildcard(const char *str) const { return nall::wildcard(data, str); }
bool string::iwildcard(const char *str) const { return nall::iwildcard(data, str); }
bool string::beginswith(const char *str) const { return strbegin(data, str); }
bool string::ibeginswith(const char *str) const { return stribegin(data, str); }
bool string::endswith(const char *str) const { return strend(data, str); }
bool string::iendswith(const char *str) const { return striend(data, str); }
string& string::lower() { nall::strlower(data); return *this; }
string& string::upper() { nall::strupper(data); return *this; }
string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; }
template<unsigned limit> string& string::ltrim(const char *key) { nall::ltrim<limit>(data, key); return *this; }
template<unsigned limit> string& string::rtrim(const char *key) { nall::rtrim<limit>(data, key); return *this; }
template<unsigned limit> string& string::trim (const char *key) { nall::trim <limit>(data, key); return *this; }
optional<unsigned> string::position(const char *key) const { return strpos(data, key); }
optional<unsigned> string::qposition(const char *key) const { return qstrpos(data, key); }
}
#endif

View File

@@ -75,11 +75,12 @@ inline string xml_element::parse() const {
if(strbegin(source, "<![CDATA[")) { if(strbegin(source, "<![CDATA[")) {
if(auto pos = strpos(source, "]]>")) { if(auto pos = strpos(source, "]]>")) {
if(pos() - 9 > 0) {
string cdata = substr(source, 9, pos() - 9); string cdata = substr(source, 9, pos() - 9);
data << cdata; data << cdata;
offset += strlen(cdata); offset += strlen(cdata);
}
source += offset + 3; source += 9 + offset + 3;
continue; continue;
} else { } else {
return ""; return "";
@@ -138,8 +139,8 @@ inline bool xml_element::parse_head(string data) {
xml_attribute attr; xml_attribute attr;
attr.name = side[0]; attr.name = side[0];
attr.content = side[1]; attr.content = side[1];
if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) attr.content.trim_once("\""); if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) attr.content.trim<1>("\"");
else if(strbegin(attr.content, "'") && strend(attr.content, "'")) attr.content.trim_once("'"); else if(strbegin(attr.content, "'") && strend(attr.content, "'")) attr.content.trim<1>("'");
else throw "..."; else throw "...";
attribute.append(attr); attribute.append(attr);
} }
@@ -185,10 +186,10 @@ inline bool xml_element::parse_body(const char *&data) {
if(strend(tag, "?") == true) { if(strend(tag, "?") == true) {
self_terminating = true; self_terminating = true;
tag.rtrim_once("?"); tag.rtrim<1>("?");
} else if(strend(tag, "/") == true) { } else if(strend(tag, "/") == true) {
self_terminating = true; self_terminating = true;
tag.rtrim_once("/"); tag.rtrim<1>("/");
} }
parse_head(tag); parse_head(tag);

View File

@@ -1,182 +1,212 @@
#ifndef NALL_UPS_HPP #ifndef NALL_UPS_HPP
#define NALL_UPS_HPP #define NALL_UPS_HPP
#include <stdio.h>
#include <nall/algorithm.hpp>
#include <nall/crc32.hpp> #include <nall/crc32.hpp>
#include <nall/file.hpp> #include <nall/file.hpp>
#include <nall/function.hpp>
#include <nall/stdint.hpp> #include <nall/stdint.hpp>
namespace nall { namespace nall {
class ups {
public: struct ups {
enum result { enum class result : unsigned {
ok, unknown,
patch_unreadable, success,
patch_unwritable, patch_unwritable,
patch_invalid, patch_invalid,
input_invalid, source_invalid,
output_invalid, target_invalid,
patch_crc32_invalid, target_too_small,
input_crc32_invalid, patch_checksum_invalid,
output_crc32_invalid, source_checksum_invalid,
target_checksum_invalid,
}; };
ups::result create(const char *patch_fn, const uint8_t *x_data, unsigned x_size, const uint8_t *y_data, unsigned y_size) { function<void (unsigned offset, unsigned length)> progress;
if(!fp.open(patch_fn, file::mode_write)) return patch_unwritable;
crc32 = ~0; result create(
uint32_t x_crc32 = crc32_calculate(x_data, x_size); const uint8_t *sourcedata, unsigned sourcelength,
uint32_t y_crc32 = crc32_calculate(y_data, y_size); const uint8_t *targetdata, unsigned targetlength,
const char *patchfilename
) {
source_data = (uint8_t*)sourcedata, target_data = (uint8_t*)targetdata;
source_length = sourcelength, target_length = targetlength;
source_offset = target_offset = 0;
source_checksum = target_checksum = patch_checksum = ~0;
//header if(patch_file.open(patchfilename, file::mode::write) == false) return result::patch_unwritable;
write('U');
write('P');
write('S');
write('1');
encptr(x_size);
encptr(y_size);
//body patch_write('U');
unsigned max_size = max(x_size, y_size); patch_write('P');
patch_write('S');
patch_write('1');
encode(source_length);
encode(target_length);
unsigned output_length = source_length > target_length ? source_length : target_length;
unsigned relative = 0; unsigned relative = 0;
for(unsigned i = 0; i < max_size;) { for(unsigned offset = 0; offset < output_length;) {
uint8_t x = i < x_size ? x_data[i] : 0x00; uint8_t x = source_read();
uint8_t y = i < y_size ? y_data[i] : 0x00; uint8_t y = target_read();
if(x == y) { if(x == y) {
i++; offset++;
continue; continue;
} }
encptr(i++ - relative); encode(offset++ - relative);
write(x ^ y); patch_write(x ^ y);
while(true) { while(true) {
if(i >= max_size) { if(offset >= output_length) {
write(0x00); patch_write(0x00);
break; break;
} }
x = i < x_size ? x_data[i] : 0x00; x = source_read();
y = i < y_size ? y_data[i] : 0x00; y = target_read();
i++; offset++;
write(x ^ y); patch_write(x ^ y);
if(x == y) break; if(x == y) break;
} }
relative = i; relative = offset;
} }
//footer source_checksum = ~source_checksum;
for(unsigned i = 0; i < 4; i++) write(x_crc32 >> (i << 3)); target_checksum = ~target_checksum;
for(unsigned i = 0; i < 4; i++) write(y_crc32 >> (i << 3)); for(unsigned i = 0; i < 4; i++) patch_write(source_checksum >> (i * 8));
uint32_t p_crc32 = ~crc32; for(unsigned i = 0; i < 4; i++) patch_write(target_checksum >> (i * 8));
for(unsigned i = 0; i < 4; i++) write(p_crc32 >> (i << 3)); uint32_t patch_result_checksum = ~patch_checksum;
for(unsigned i = 0; i < 4; i++) patch_write(patch_result_checksum >> (i * 8));
fp.close(); patch_file.close();
return ok; return result::success;
} }
ups::result apply(const uint8_t *p_data, unsigned p_size, const uint8_t *x_data, unsigned x_size, uint8_t *&y_data, unsigned &y_size) { result apply(
if(p_size < 18) return patch_invalid; const uint8_t *patchdata, unsigned patchlength,
p_buffer = p_data; const uint8_t *sourcedata, unsigned sourcelength,
uint8_t *targetdata, unsigned &targetlength
) {
patch_data = (uint8_t*)patchdata, source_data = (uint8_t*)sourcedata, target_data = targetdata;
patch_length = patchlength, source_length = sourcelength, target_length = targetlength;
patch_offset = source_offset = target_offset = 0;
patch_checksum = source_checksum = target_checksum = ~0;
crc32 = ~0; if(patch_length < 18) return result::patch_invalid;
if(patch_read() != 'U') return result::patch_invalid;
if(patch_read() != 'P') return result::patch_invalid;
if(patch_read() != 'S') return result::patch_invalid;
if(patch_read() != '1') return result::patch_invalid;
//header unsigned source_read_length = decode();
if(read() != 'U') return patch_invalid; unsigned target_read_length = decode();
if(read() != 'P') return patch_invalid;
if(read() != 'S') return patch_invalid;
if(read() != '1') return patch_invalid;
unsigned px_size = decptr(); if(source_length != source_read_length && source_length != target_read_length) return result::source_invalid;
unsigned py_size = decptr(); targetlength = (source_length == source_read_length ? target_read_length : source_read_length);
if(target_length < targetlength) return result::target_too_small;
//mirror target_length = targetlength;
if(x_size != px_size && x_size != py_size) return input_invalid;
y_size = (x_size == px_size) ? py_size : px_size;
y_data = new uint8_t[y_size]();
for(unsigned i = 0; i < x_size && i < y_size; i++) y_data[i] = x_data[i];
for(unsigned i = x_size; i < y_size; i++) y_data[i] = 0x00;
//body
unsigned relative = 0;
while(p_buffer < p_data + p_size - 12) {
relative += decptr();
while(patch_offset < patch_length - 12) {
unsigned length = decode();
while(length--) target_write(source_read());
while(true) { while(true) {
uint8_t x = read(); uint8_t patch_xor = patch_read();
if(x && relative < y_size) { target_write(patch_xor ^ source_read());
uint8_t y = relative < x_size ? x_data[relative] : 0x00; if(patch_xor == 0) break;
y_data[relative] = x ^ y;
}
relative++;
if(!x) break;
} }
} }
//footer uint32_t patch_read_checksum = 0, source_read_checksum = 0, target_read_checksum = 0;
unsigned px_crc32 = 0, py_crc32 = 0, pp_crc32 = 0; for(unsigned i = 0; i < 4; i++) source_read_checksum |= patch_read() << (i * 8);
for(unsigned i = 0; i < 4; i++) px_crc32 |= read() << (i << 3); for(unsigned i = 0; i < 4; i++) target_read_checksum |= patch_read() << (i * 8);
for(unsigned i = 0; i < 4; i++) py_crc32 |= read() << (i << 3); uint32_t patch_result_checksum = ~patch_checksum;
uint32_t p_crc32 = ~crc32; source_checksum = ~source_checksum;
for(unsigned i = 0; i < 4; i++) pp_crc32 |= read() << (i << 3); target_checksum = ~target_checksum;
for(unsigned i = 0; i < 4; i++) patch_read_checksum |= patch_read() << (i * 8);
uint32_t x_crc32 = crc32_calculate(x_data, x_size); if(patch_result_checksum != patch_read_checksum) return result::patch_invalid;
uint32_t y_crc32 = crc32_calculate(y_data, y_size); if(source_checksum == source_read_checksum && source_length == source_read_length) {
if(target_checksum == target_read_checksum && target_length == target_read_length) return result::success;
if(px_size != py_size) { return result::target_invalid;
if(x_size == px_size && x_crc32 != px_crc32) return input_crc32_invalid; } else if(source_checksum == target_read_checksum && source_length == target_read_length) {
if(x_size == py_size && x_crc32 != py_crc32) return input_crc32_invalid; if(target_checksum == source_read_checksum && target_length == source_read_length) return result::success;
if(y_size == px_size && y_crc32 != px_crc32) return output_crc32_invalid; return result::target_invalid;
if(y_size == py_size && y_crc32 != py_crc32) return output_crc32_invalid;
} else { } else {
if(x_crc32 != px_crc32 && x_crc32 != py_crc32) return input_crc32_invalid; return result::source_invalid;
if(y_crc32 != px_crc32 && y_crc32 != py_crc32) return output_crc32_invalid;
if(x_crc32 == y_crc32 && px_crc32 != py_crc32) return output_crc32_invalid;
if(x_crc32 != y_crc32 && px_crc32 == py_crc32) return output_crc32_invalid;
} }
if(p_crc32 != pp_crc32) return patch_crc32_invalid;
return ok;
} }
private: private:
file fp; uint8_t *patch_data, *source_data, *target_data;
uint32_t crc32; unsigned patch_length, source_length, target_length;
const uint8_t *p_buffer; unsigned patch_offset, source_offset, target_offset;
unsigned patch_checksum, source_checksum, target_checksum;
file patch_file;
uint8_t read() { uint8_t patch_read() {
uint8_t n = *p_buffer++; if(patch_offset < patch_length) {
crc32 = crc32_adjust(crc32, n); uint8_t n = patch_data[patch_offset++];
patch_checksum = crc32_adjust(patch_checksum, n);
return n; return n;
} }
return 0x00;
void write(uint8_t n) {
fp.write(n);
crc32 = crc32_adjust(crc32, n);
} }
void encptr(uint64_t offset) { uint8_t source_read() {
if(source_offset < source_length) {
uint8_t n = source_data[source_offset++];
source_checksum = crc32_adjust(source_checksum, n);
return n;
}
return 0x00;
}
uint8_t target_read() {
uint8_t result = 0x00;
if(target_offset < target_length) {
result = target_data[target_offset];
target_checksum = crc32_adjust(target_checksum, result);
}
if(((target_offset++ & 255) == 0) && progress) {
progress(target_offset, source_length > target_length ? source_length : target_length);
}
return result;
}
void patch_write(uint8_t n) {
patch_file.write(n);
patch_checksum = crc32_adjust(patch_checksum, n);
}
void target_write(uint8_t n) {
if(target_offset < target_length) {
target_data[target_offset] = n;
target_checksum = crc32_adjust(target_checksum, n);
}
if(((target_offset++ & 255) == 0) && progress) {
progress(target_offset, source_length > target_length ? source_length : target_length);
}
}
void encode(uint64_t offset) {
while(true) { while(true) {
uint64_t x = offset & 0x7f; uint64_t x = offset & 0x7f;
offset >>= 7; offset >>= 7;
if(offset == 0) { if(offset == 0) {
write(0x80 | x); patch_write(0x80 | x);
break; break;
} }
write(x); patch_write(x);
offset--; offset--;
} }
} }
uint64_t decptr() { uint64_t decode() {
uint64_t offset = 0, shift = 1; uint64_t offset = 0, shift = 1;
while(true) { while(true) {
uint8_t x = read(); uint8_t x = patch_read();
offset += (x & 0x7f) * shift; offset += (x & 0x7f) * shift;
if(x & 0x80) break; if(x & 0x80) break;
shift <<= 7; shift <<= 7;
@@ -185,6 +215,7 @@ namespace nall {
return offset; return offset;
} }
}; };
} }
#endif #endif

View File

@@ -2,8 +2,9 @@ static void Button_tick(Button *self) {
if(self->onTick) self->onTick(); if(self->onTick) self->onTick();
} }
void Button::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void Button::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
object->widget = gtk_button_new_with_label(text); object->widget = gtk_button_new_with_label(text);
widget->parent = &parent;
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
g_signal_connect_swapped(G_OBJECT(object->widget), "clicked", G_CALLBACK(Button_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "clicked", G_CALLBACK(Button_tick), (gpointer)this);
if(parent.window->defaultFont) setFont(*parent.window->defaultFont); if(parent.window->defaultFont) setFont(*parent.window->defaultFont);

View File

@@ -22,6 +22,7 @@ void Canvas::create(Window &parent, unsigned x, unsigned y, unsigned width, unsi
canvas->pitch = width * sizeof(uint32_t); canvas->pitch = width * sizeof(uint32_t);
object->widget = gtk_drawing_area_new(); object->widget = gtk_drawing_area_new();
widget->parent = &parent;
GdkColor color; GdkColor color;
color.pixel = color.red = color.green = color.blue = 0; color.pixel = color.red = color.green = color.blue = 0;
gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color); gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color);

View File

@@ -2,8 +2,9 @@ static void CheckBox_tick(CheckBox *self) {
if(self->onTick && self->object->locked == false) self->onTick(); if(self->onTick && self->object->locked == false) self->onTick();
} }
void CheckBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void CheckBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
object->widget = gtk_check_button_new_with_label(text); object->widget = gtk_check_button_new_with_label(text);
widget->parent = &parent;
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(CheckBox_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(CheckBox_tick), (gpointer)this);
if(parent.window->defaultFont) setFont(*parent.window->defaultFont); if(parent.window->defaultFont) setFont(*parent.window->defaultFont);

View File

@@ -2,8 +2,9 @@ void ComboBox_change(ComboBox *self) {
if(self->object->locked == false && self->onChange) self->onChange(); if(self->object->locked == false && self->onChange) self->onChange();
} }
void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
object->widget = gtk_combo_box_new_text(); object->widget = gtk_combo_box_new_text();
widget->parent = &parent;
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
g_signal_connect_swapped(G_OBJECT(object->widget), "changed", G_CALLBACK(ComboBox_change), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "changed", G_CALLBACK(ComboBox_change), (gpointer)this);
@@ -27,7 +28,7 @@ void ComboBox::reset() {
counter = 0; counter = 0;
} }
void ComboBox::addItem(const char *text) { void ComboBox::addItem(const string &text) {
gtk_combo_box_append_text(GTK_COMBO_BOX(object->widget), text); gtk_combo_box_append_text(GTK_COMBO_BOX(object->widget), text);
if(counter++ == 0) setSelection(0); if(counter++ == 0) setSelection(0);
} }

View File

@@ -2,8 +2,9 @@ static void EditBox_change(EditBox *self) {
if(self->object->locked == false && self->onChange) self->onChange(); if(self->object->locked == false && self->onChange) self->onChange();
} }
void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
object->widget = gtk_scrolled_window_new(0, 0); object->widget = gtk_scrolled_window_new(0, 0);
widget->parent = &parent;
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN);
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
@@ -41,7 +42,7 @@ string EditBox::text() {
return text; return text;
} }
void EditBox::setText(const char *text) { void EditBox::setText(const string &text) {
object->locked = true; object->locked = true;
gtk_text_buffer_set_text(object->textBuffer, text, -1); gtk_text_buffer_set_text(object->textBuffer, text, -1);
object->locked = false; object->locked = false;

View File

@@ -1,4 +1,4 @@
bool Font::create(const char *name, unsigned size, Font::Style style) { bool Font::create(const string &name, unsigned size, Font::Style style) {
font->font = pango_font_description_new(); font->font = pango_font_description_new();
pango_font_description_set_family(font->font, name); pango_font_description_set_family(font->font, name);
pango_font_description_set_size(font->font, size * PANGO_SCALE); pango_font_description_set_size(font->font, size * PANGO_SCALE);

View File

@@ -37,12 +37,30 @@ namespace phoenix {
#include "viewport.cpp" #include "viewport.cpp"
#include "messagewindow.cpp" #include "messagewindow.cpp"
OS &os = OS::handle();
Window Window::None; Window Window::None;
OS& OS::handle() { void OS::initialize() {
static OS os; static bool initialized = false;
return os; if(initialized == true) return;
initialized = true;
int argc = 1;
char *argv[2];
argv[0] = new char[8];
argv[1] = 0;
strcpy(argv[0], "phoenix");
char **argvp = argv;
gtk_init(&argc, &argvp);
gtk_rc_parse_string(
"style \"phoenix-gtk\"\n"
"{\n"
" GtkComboBox::appears-as-list = 1\n"
" GtkTreeView::vertical-separator = 0\n"
"}\n"
"class \"GtkComboBox\" style \"phoenix-gtk\"\n"
"class \"GtkTreeView\" style \"phoenix-gtk\"\n"
);
} }
bool OS::pending() { bool OS::pending() {
@@ -69,7 +87,7 @@ unsigned OS::desktopHeight() {
return gdk_screen_get_height(gdk_screen_get_default()); return gdk_screen_get_height(gdk_screen_get_default());
} }
string OS::folderSelect(Window &parent, const char *path) { string OS::folderSelect(Window &parent, const string &path) {
string name; string name;
GtkWidget *dialog = gtk_file_chooser_dialog_new( GtkWidget *dialog = gtk_file_chooser_dialog_new(
@@ -90,10 +108,11 @@ string OS::folderSelect(Window &parent, const char *path) {
} }
gtk_widget_destroy(dialog); gtk_widget_destroy(dialog);
if(name.endswith("/") == false) name.append("/");
return name; return name;
} }
string OS::fileOpen(Window &parent, const char *filter, const char *path) { string OS::fileOpen(Window &parent, const string &filter, const string &path) {
string name; string name;
GtkWidget *dialog = gtk_file_chooser_dialog_new( GtkWidget *dialog = gtk_file_chooser_dialog_new(
@@ -130,7 +149,7 @@ string OS::fileOpen(Window &parent, const char *filter, const char *path) {
return name; return name;
} }
string OS::fileSave(Window &parent, const char *filter, const char *path) { string OS::fileSave(Window &parent, const string &filter, const string &path) {
string name; string name;
GtkWidget *dialog = gtk_file_chooser_dialog_new( GtkWidget *dialog = gtk_file_chooser_dialog_new(
@@ -167,25 +186,4 @@ string OS::fileSave(Window &parent, const char *filter, const char *path) {
return name; return name;
} }
OS::OS() {
os = new OS::Data;
int argc = 1;
char *argv[2];
argv[0] = new char[8];
argv[1] = 0;
strcpy(argv[0], "phoenix");
char **argvp = argv;
gtk_init(&argc, &argvp);
gtk_rc_parse_string(
"style \"phoenix-gtk\"\n"
"{\n"
" GtkComboBox::appears-as-list = 1\n"
" GtkTreeView::vertical-separator = 0\n"
"}\n"
"class \"GtkComboBox\" style \"phoenix-gtk\"\n"
"class \"GtkTreeView\" style \"phoenix-gtk\"\n"
);
}
} }

View File

@@ -12,13 +12,20 @@ struct Object {
Data *object; Data *object;
}; };
struct Geometry {
unsigned x, y;
unsigned width, height;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(unsigned x, unsigned y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
};
struct Font : Object { struct Font : Object {
enum class Style : unsigned { enum class Style : unsigned {
None = 0, None = 0,
Bold = 1, Bold = 1,
Italic = 2, Italic = 2,
}; };
bool create(const char *name, unsigned size, Font::Style style = Style::None); bool create(const nall::string &name, unsigned size, Font::Style style = Style::None);
Font(); Font();
~Font(); ~Font();
//private: //private:
@@ -30,16 +37,19 @@ inline Font::Style operator|(Font::Style a, Font::Style b) { return (Font::Style
inline Font::Style operator&(Font::Style a, Font::Style b) { return (Font::Style)((unsigned)a & (unsigned)b); } inline Font::Style operator&(Font::Style a, Font::Style b) { return (Font::Style)((unsigned)a & (unsigned)b); }
struct Action : Object { struct Action : Object {
void setFont(Font &font);
bool visible(); bool visible();
void setVisible(bool visible = true); void setVisible(bool visible = true);
bool enabled(); bool enabled();
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
Action();
//private:
struct Data;
Data *action;
}; };
struct Menu : Action { struct Menu : Action {
void create(Window &parent, const char *text); void create(Window &parent, const nall::string &text);
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
}; };
struct MenuSeparator : Action { struct MenuSeparator : Action {
@@ -48,20 +58,20 @@ struct MenuSeparator : Action {
struct MenuItem : Action { struct MenuItem : Action {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
}; };
struct MenuCheckItem : Action { struct MenuCheckItem : Action {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
bool checked(); bool checked();
void setChecked(bool checked = true); void setChecked(bool checked = true);
}; };
struct MenuRadioItem : Action { struct MenuRadioItem : Action {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
void create(MenuRadioItem &parent, const char *text); void create(MenuRadioItem &parent, const nall::string &text);
bool checked(); bool checked();
void setChecked(); void setChecked();
private: private:
@@ -76,31 +86,37 @@ struct Widget : Object {
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
virtual bool focused(); virtual bool focused();
virtual void setFocused(); virtual void setFocused();
virtual void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
Widget();
//private:
struct Data;
Data *widget;
}; };
struct Window : Widget { struct Window : Widget {
static Window None;
nall::function<bool ()> onClose; nall::function<bool ()> onClose;
void create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
bool focused(); bool focused();
void setFocused(); void setFocused();
Geometry geometry();
void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height); void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
void setDefaultFont(Font &font); void setDefaultFont(Font &font);
void setFont(Font &font); void setFont(Font &font);
void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue); void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
void setTitle(const char *text); void setTitle(const nall::string &text);
void setStatusText(const char *text); void setStatusText(const nall::string &text);
void setMenuVisible(bool visible = true); void setMenuVisible(bool visible = true);
void setStatusVisible(bool visible = true); void setStatusVisible(bool visible = true);
Window(); Window();
//private: //private:
struct Data; struct Data;
Data *window; Data *window;
static Window None;
}; };
struct Button : Widget { struct Button : Widget {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
}; };
struct Canvas : Widget { struct Canvas : Widget {
@@ -116,16 +132,16 @@ struct Canvas : Widget {
struct CheckBox : Widget { struct CheckBox : Widget {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
bool checked(); bool checked();
void setChecked(bool checked = true); void setChecked(bool checked = true);
}; };
struct ComboBox : Widget { struct ComboBox : Widget {
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void reset(); void reset();
void addItem(const char *text); void addItem(const nall::string &text);
unsigned selection(); unsigned selection();
void setSelection(unsigned item); void setSelection(unsigned item);
ComboBox(); ComboBox();
@@ -135,12 +151,12 @@ private:
struct EditBox : Widget { struct EditBox : Widget {
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setFocused(); void setFocused();
void setEditable(bool editable = true); void setEditable(bool editable = true);
void setWordWrap(bool wordWrap = true); void setWordWrap(bool wordWrap = true);
nall::string text(); nall::string text();
void setText(const char *text); void setText(const nall::string &text);
}; };
struct HorizontalSlider : Widget { struct HorizontalSlider : Widget {
@@ -151,21 +167,25 @@ struct HorizontalSlider : Widget {
}; };
struct Label : Widget { struct Label : Widget {
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setText(const char *text); void setText(const nall::string &text);
}; };
struct ListBox : Widget { struct ListBox : Widget {
nall::function<void ()> onActivate; nall::function<void ()> onActivate;
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); nall::function<void (unsigned)> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setFocused(); void setFocused();
void setHeaderVisible(bool headerVisible = true); void setHeaderVisible(bool headerVisible = true);
void setCheckable(bool checkable = true);
void setFont(Font &font); void setFont(Font &font);
void reset(); void reset();
void resizeColumnsToContent(); void resizeColumnsToContent();
void addItem(const char *text); void addItem(const nall::string &text);
void setItem(unsigned row, const char *text); void setItem(unsigned row, const nall::string &text);
bool checked(unsigned row);
void setChecked(unsigned row, bool checked = true);
nall::optional<unsigned> selection(); nall::optional<unsigned> selection();
void setSelection(unsigned row); void setSelection(unsigned row);
ListBox(); ListBox();
@@ -176,13 +196,13 @@ struct ListBox : Widget {
struct ProgressBar : Widget { struct ProgressBar : Widget {
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height);
void setProgress(unsigned progress); void setPosition(unsigned position);
}; };
struct RadioBox : Widget { struct RadioBox : Widget {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
bool checked(); bool checked();
void setChecked(); void setChecked();
private: private:
@@ -190,11 +210,12 @@ private:
}; };
struct TextBox : Widget { struct TextBox : Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setEditable(bool editable = true); void setEditable(bool editable = true);
nall::string text(); nall::string text();
void setText(const char *text); void setText(const nall::string &text);
}; };
struct VerticalSlider : Widget { struct VerticalSlider : Widget {
@@ -221,30 +242,24 @@ struct MessageWindow : Object {
Yes, Yes,
No, No,
}; };
static Response information(Window &parent, const char *text, Buttons = Buttons::Ok); static Response information(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response question(Window &parent, const char *text, Buttons = Buttons::YesNo); static Response question(Window &parent, const nall::string &text, Buttons = Buttons::YesNo);
static Response warning(Window &parent, const char *text, Buttons = Buttons::Ok); static Response warning(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response critical(Window &parent, const char *text, Buttons = Buttons::Ok); static Response critical(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
}; };
struct OS : Object { struct OS : Object {
bool pending(); static bool pending();
void run(); static void run();
void main(); static void main();
void quit(); static void quit();
unsigned desktopWidth(); static unsigned desktopWidth();
unsigned desktopHeight(); static unsigned desktopHeight();
nall::string folderSelect(Window &parent, const char *path = ""); static nall::string folderSelect(Window &parent, const nall::string &path = "");
nall::string fileOpen(Window &parent, const char *filter, const char *path = ""); static nall::string fileOpen(Window &parent, const nall::string &filter, const nall::string &path = "");
nall::string fileSave(Window &parent, const char *filter, const char *path = ""); static nall::string fileSave(Window &parent, const nall::string &filter, const nall::string &path = "");
//private: //private:
static OS& handle(); static void initialize();
struct Data;
Data *os;
private:
OS();
}; };
extern OS &os;
} }

View File

@@ -8,6 +8,7 @@ void HorizontalSlider::create(Window &parent, unsigned x, unsigned y, unsigned w
object->position = 0; object->position = 0;
length += (length == 0); length += (length == 0);
object->widget = gtk_hscale_new_with_range(0, length - 1, 1); object->widget = gtk_hscale_new_with_range(0, length - 1, 1);
widget->parent = &parent;
gtk_scale_set_draw_value(GTK_SCALE(object->widget), false); gtk_scale_set_draw_value(GTK_SCALE(object->widget), false);
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
g_signal_connect_swapped(G_OBJECT(object->widget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)this);

View File

@@ -1,5 +1,6 @@
void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
object->widget = gtk_label_new(text); object->widget = gtk_label_new(text);
widget->parent = &parent;
gtk_misc_set_alignment(GTK_MISC(object->widget), 0.0, 0.5); gtk_misc_set_alignment(GTK_MISC(object->widget), 0.0, 0.5);
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
if(parent.window->defaultFont) setFont(*parent.window->defaultFont); if(parent.window->defaultFont) setFont(*parent.window->defaultFont);
@@ -7,6 +8,6 @@ void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsig
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
void Label::setText(const char *text) { void Label::setText(const string &text) {
gtk_label_set_text(GTK_LABEL(object->widget), text); gtk_label_set_text(GTK_LABEL(object->widget), text);
} }

View File

@@ -1,3 +1,10 @@
static void ListBox_activate(ListBox *self) {
signed selection = -1;
if(auto position = self->selection()) selection = position();
self->listBox->selection = selection;
if(self->onActivate) self->onActivate();
}
static void ListBox_change(ListBox *self) { static void ListBox_change(ListBox *self) {
signed selection = -1; signed selection = -1;
if(auto position = self->selection()) selection = position(); if(auto position = self->selection()) selection = position();
@@ -6,25 +13,25 @@ static void ListBox_change(ListBox *self) {
if(self->onChange) self->onChange(); if(self->onChange) self->onChange();
} }
static void ListBox_activate(ListBox *self) { static void ListBox_tick(GtkCellRendererToggle *cell, gchar *path_string, ListBox *self) {
signed selection = -1; unsigned index = strunsigned(path_string);
if(auto position = self->selection()) selection = position(); self->setChecked(index, !self->checked(index));
self->listBox->selection = selection; if(self->onTick) self->onTick(index);
if(self->onActivate) self->onActivate();
} }
void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
listBox->selection = -1; listBox->selection = -1;
object->widget = gtk_scrolled_window_new(0, 0); object->widget = gtk_scrolled_window_new(0, 0);
widget->parent = &parent;
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN);
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
lstring list; lstring list;
list.split("\t", text); list.split("\t", string("\t", text));
GType *v = (GType*)malloc(list.size() * sizeof(GType)); GType *v = (GType*)malloc(list.size() * sizeof(GType));
for(unsigned i = 0; i < list.size(); i++) v[i] = G_TYPE_STRING; for(unsigned i = 0; i < list.size(); i++) v[i] = (i == 0 ? G_TYPE_BOOLEAN : G_TYPE_STRING);
listBox->store = gtk_list_store_newv(list.size(), v); listBox->store = gtk_list_store_newv(list.size(), v);
free(v); free(v);
@@ -32,20 +39,30 @@ void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
gtk_container_add(GTK_CONTAINER(object->widget), object->subWidget); gtk_container_add(GTK_CONTAINER(object->widget), object->subWidget);
g_object_unref(G_OBJECT(listBox->store)); g_object_unref(G_OBJECT(listBox->store));
//alternate color of each row if there is more than one column
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(object->subWidget), list.size() >= 2);
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), false);
for(unsigned i = 0; i < list.size(); i++) { for(unsigned i = 0; i < list.size(); i++) {
if(i == 0) {
listBox->column[i].renderer = gtk_cell_renderer_toggle_new();
listBox->column[i].column = gtk_tree_view_column_new_with_attributes(
"", listBox->column[i].renderer, "active", i, (void*)0
);
gtk_tree_view_column_set_resizable(listBox->column[i].column, false);
gtk_tree_view_column_set_visible(listBox->column[i].column, listBox->checkable);
g_signal_connect(listBox->column[i].renderer, "toggled", G_CALLBACK(ListBox_tick), (gpointer)this);
} else {
listBox->column[i].renderer = gtk_cell_renderer_text_new(); listBox->column[i].renderer = gtk_cell_renderer_text_new();
listBox->column[i].column = gtk_tree_view_column_new_with_attributes( listBox->column[i].column = gtk_tree_view_column_new_with_attributes(
list[i], listBox->column[i].renderer, "text", i, (void*)0 "", listBox->column[i].renderer, "text", i, (void*)0
); );
gtk_tree_view_column_set_resizable(listBox->column[i].column, true);
}
listBox->column[i].label = gtk_label_new(list[i]); listBox->column[i].label = gtk_label_new(list[i]);
gtk_tree_view_column_set_widget(GTK_TREE_VIEW_COLUMN(listBox->column[i].column), listBox->column[i].label); gtk_tree_view_column_set_widget(GTK_TREE_VIEW_COLUMN(listBox->column[i].column), listBox->column[i].label);
gtk_tree_view_append_column(GTK_TREE_VIEW(object->subWidget), listBox->column[i].column); gtk_tree_view_append_column(GTK_TREE_VIEW(object->subWidget), listBox->column[i].column);
gtk_widget_show(listBox->column[i].label); gtk_widget_show(listBox->column[i].label);
} }
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), false);
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(object->subWidget), list.size() >= 3); //>= 2 + one for the checkbox column
gtk_tree_view_set_search_column(GTK_TREE_VIEW(object->subWidget), 1);
g_signal_connect_swapped(G_OBJECT(object->subWidget), "cursor-changed", G_CALLBACK(ListBox_change), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->subWidget), "cursor-changed", G_CALLBACK(ListBox_change), (gpointer)this);
g_signal_connect_swapped(G_OBJECT(object->subWidget), "row-activated", G_CALLBACK(ListBox_activate), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->subWidget), "row-activated", G_CALLBACK(ListBox_activate), (gpointer)this);
@@ -64,6 +81,11 @@ void ListBox::setHeaderVisible(bool visible) {
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), visible); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), visible);
} }
void ListBox::setCheckable(bool checkable) {
listBox->checkable = checkable;
if(object->subWidget) gtk_tree_view_column_set_visible(listBox->column[0].column, checkable);
}
void ListBox::setFont(Font &font) { void ListBox::setFont(Font &font) {
Widget::setFont(font); Widget::setFont(font);
unsigned columns = 1; unsigned columns = 1;
@@ -89,17 +111,16 @@ void ListBox::resizeColumnsToContent() {
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(object->subWidget)); gtk_tree_view_columns_autosize(GTK_TREE_VIEW(object->subWidget));
} }
void ListBox::addItem(const char *text) { void ListBox::addItem(const string &text) {
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
GtkTreeIter iter; GtkTreeIter iter;
gtk_list_store_append(listBox->store, &iter); gtk_list_store_append(listBox->store, &iter);
for(unsigned i = 0; i < list.size(); i++) { unsigned index = 1;
gtk_list_store_set(listBox->store, &iter, i, (const char*)list[i], -1); foreach(item, list) gtk_list_store_set(listBox->store, &iter, index++, (const char*)item, -1);
}
} }
void ListBox::setItem(unsigned row, const char *text) { void ListBox::setItem(unsigned row, const string &text) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget)); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
GtkTreeIter iter; GtkTreeIter iter;
for(unsigned i = 0; i <= row; i++) { for(unsigned i = 0; i <= row; i++) {
@@ -109,9 +130,28 @@ void ListBox::setItem(unsigned row, const char *text) {
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) { unsigned index = 1;
gtk_list_store_set(listBox->store, &iter, i, (const char*)list[i], -1); foreach(item, list) gtk_list_store_set(listBox->store, &iter, index++, (const char*)item, -1);
} }
bool ListBox::checked(unsigned row) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
GtkTreePath *path = gtk_tree_path_new_from_string(string(row));
GtkTreeIter iter;
bool state;
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_model_get(model, &iter, 0, &state, -1);
gtk_tree_path_free(path);
return state;
}
void ListBox::setChecked(unsigned row, bool checked) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
GtkTreePath *path = gtk_tree_path_new_from_string(string(row));
GtkTreeIter iter;
gtk_tree_model_get_iter(model, &iter, path);
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, checked, -1);
gtk_tree_path_free(path);
} }
optional<unsigned> ListBox::selection() { optional<unsigned> ListBox::selection() {
@@ -151,4 +191,5 @@ void ListBox::setSelection(unsigned row) {
ListBox::ListBox() { ListBox::ListBox() {
listBox = new ListBox::Data; listBox = new ListBox::Data;
listBox->checkable = false;
} }

View File

@@ -1,12 +1,10 @@
static void Action_setFont(GtkWidget *widget, gpointer font) { static void Action_setFont(GtkWidget *widget, gpointer font) {
if(font) {
gtk_widget_modify_font(widget, (PangoFontDescription*)font); gtk_widget_modify_font(widget, (PangoFontDescription*)font);
if(GTK_IS_CONTAINER(widget)) { if(GTK_IS_CONTAINER(widget)) {
gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)Action_setFont, font); gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)Action_setFont, (PangoFontDescription*)font);
} }
} }
void Action::setFont(Font &font) {
Action_setFont(object->widget, font.font->font);
} }
bool Action::visible() { bool Action::visible() {
@@ -25,25 +23,35 @@ void Action::setEnabled(bool enabled) {
gtk_widget_set_sensitive(object->widget, enabled); gtk_widget_set_sensitive(object->widget, enabled);
} }
void Menu::create(Window &parent, const char *text) { Action::Action() {
action = new Action::Data;
action->font = 0;
}
void Menu::create(Window &parent, const string &text) {
action->font = parent.window->defaultFont;
object->menu = gtk_menu_new(); object->menu = gtk_menu_new();
object->widget = gtk_menu_item_new_with_label(text); object->widget = gtk_menu_item_new_with_label(text);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(object->widget), object->menu); gtk_menu_item_set_submenu(GTK_MENU_ITEM(object->widget), object->menu);
if(parent.window->defaultFont) setFont(*parent.window->defaultFont); if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_bar_append(parent.object->menu, object->widget); gtk_menu_bar_append(parent.object->menu, object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
void Menu::create(Menu &parent, const char *text) { void Menu::create(Menu &parent, const string &text) {
action->font = parent.action->font;
object->menu = gtk_menu_new(); object->menu = gtk_menu_new();
object->widget = gtk_menu_item_new_with_label(text); object->widget = gtk_menu_item_new_with_label(text);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(object->widget), object->menu); gtk_menu_item_set_submenu(GTK_MENU_ITEM(object->widget), object->menu);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
void MenuSeparator::create(Menu &parent) { void MenuSeparator::create(Menu &parent) {
action->font = parent.action->font;
object->widget = gtk_separator_menu_item_new(); object->widget = gtk_separator_menu_item_new();
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
@@ -52,9 +60,11 @@ static void MenuItem_tick(MenuItem *self) {
if(self->onTick) self->onTick(); if(self->onTick) self->onTick();
} }
void MenuItem::create(Menu &parent, const char *text) { void MenuItem::create(Menu &parent, const string &text) {
action->font = parent.action->font;
object->widget = gtk_menu_item_new_with_label(text); object->widget = gtk_menu_item_new_with_label(text);
g_signal_connect_swapped(G_OBJECT(object->widget), "activate", G_CALLBACK(MenuItem_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "activate", G_CALLBACK(MenuItem_tick), (gpointer)this);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
@@ -63,9 +73,11 @@ static void MenuCheckItem_tick(MenuCheckItem *self) {
if(self->onTick && self->object->locked == false) self->onTick(); if(self->onTick && self->object->locked == false) self->onTick();
} }
void MenuCheckItem::create(Menu &parent, const char *text) { void MenuCheckItem::create(Menu &parent, const string &text) {
action->font = parent.action->font;
object->widget = gtk_check_menu_item_new_with_label(text); object->widget = gtk_check_menu_item_new_with_label(text);
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuCheckItem_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuCheckItem_tick), (gpointer)this);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
@@ -84,20 +96,24 @@ static void MenuRadioItem_tick(MenuRadioItem *self) {
if(self->onTick && self->checked() && self->object->locked == false) self->onTick(); if(self->onTick && self->checked() && self->object->locked == false) self->onTick();
} }
void MenuRadioItem::create(Menu &parent, const char *text) { void MenuRadioItem::create(Menu &parent, const string &text) {
first = this; first = this;
action->font = parent.action->font;
object->parentMenu = &parent; object->parentMenu = &parent;
object->widget = gtk_radio_menu_item_new_with_label(0, text); object->widget = gtk_radio_menu_item_new_with_label(0, text);
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuRadioItem_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuRadioItem_tick), (gpointer)this);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(parent.object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
void MenuRadioItem::create(MenuRadioItem &parent, const char *text) { void MenuRadioItem::create(MenuRadioItem &parent, const string &text) {
first = parent.first; first = parent.first;
action->font = parent.action->font;
object->parentMenu = parent.object->parentMenu; object->parentMenu = parent.object->parentMenu;
object->widget = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(first->object->widget), text); object->widget = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(first->object->widget), text);
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuRadioItem_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuRadioItem_tick), (gpointer)this);
if(action->font) Action_setFont(object->widget, action->font->font->font);
gtk_menu_shell_append(GTK_MENU_SHELL(object->parentMenu->object->menu), object->widget); gtk_menu_shell_append(GTK_MENU_SHELL(object->parentMenu->object->menu), object->widget);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }

View File

@@ -8,56 +8,56 @@ static MessageWindow::Response MessageWindow_response(MessageWindow::Buttons but
return MessageWindow::Response::Ok; return MessageWindow::Response::Ok;
} }
MessageWindow::Response MessageWindow::information(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) {
GtkButtonsType buttonsType = GTK_BUTTONS_OK; GtkButtonsType buttonsType = GTK_BUTTONS_OK;
if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL; if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL;
if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO; if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO;
GtkWidget *dialog = gtk_message_dialog_new( GtkWidget *dialog = gtk_message_dialog_new(
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0, &parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, buttonsType, "%s", text GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, buttonsType, "%s", (const char*)text
); );
gint response = gtk_dialog_run(GTK_DIALOG(dialog)); gint response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog); gtk_widget_destroy(dialog);
return MessageWindow_response(buttons, response); return MessageWindow_response(buttons, response);
} }
MessageWindow::Response MessageWindow::question(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) {
GtkButtonsType buttonsType = GTK_BUTTONS_OK; GtkButtonsType buttonsType = GTK_BUTTONS_OK;
if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL; if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL;
if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO; if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO;
GtkWidget *dialog = gtk_message_dialog_new( GtkWidget *dialog = gtk_message_dialog_new(
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0, &parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, buttonsType, "%s", text GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, buttonsType, "%s", (const char*)text
); );
gint response = gtk_dialog_run(GTK_DIALOG(dialog)); gint response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog); gtk_widget_destroy(dialog);
return MessageWindow_response(buttons, response); return MessageWindow_response(buttons, response);
} }
MessageWindow::Response MessageWindow::warning(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) {
GtkButtonsType buttonsType = GTK_BUTTONS_OK; GtkButtonsType buttonsType = GTK_BUTTONS_OK;
if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL; if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL;
if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO; if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO;
GtkWidget *dialog = gtk_message_dialog_new( GtkWidget *dialog = gtk_message_dialog_new(
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0, &parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, buttonsType, "%s", text GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, buttonsType, "%s", (const char*)text
); );
gint response = gtk_dialog_run(GTK_DIALOG(dialog)); gint response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog); gtk_widget_destroy(dialog);
return MessageWindow_response(buttons, response); return MessageWindow_response(buttons, response);
} }
MessageWindow::Response MessageWindow::critical(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) {
GtkButtonsType buttonsType = GTK_BUTTONS_OK; GtkButtonsType buttonsType = GTK_BUTTONS_OK;
if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL; if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL;
if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO; if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO;
GtkWidget *dialog = gtk_message_dialog_new( GtkWidget *dialog = gtk_message_dialog_new(
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0, &parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, buttonsType, "%s", text GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, buttonsType, "%s", (const char*)text
); );
gint response = gtk_dialog_run(GTK_DIALOG(dialog)); gint response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog); gtk_widget_destroy(dialog);

View File

@@ -17,6 +17,14 @@ struct Font::Data {
PangoFontDescription *font; PangoFontDescription *font;
}; };
struct Action::Data {
Font *font;
};
struct Widget::Data {
Window *parent;
};
struct Window::Data { struct Window::Data {
Font *defaultFont; Font *defaultFont;
}; };
@@ -35,16 +43,15 @@ struct ListBox::Data {
GtkWidget *label; GtkWidget *label;
}; };
linear_vector<GtkColumn> column; linear_vector<GtkColumn> column;
bool checkable;
signed selection; signed selection;
}; };
struct OS::Data {
};
void Object::unused() { void Object::unused() {
} }
Object::Object() { Object::Object() {
OS::initialize();
object = new Object::Data; object = new Object::Data;
object->locked = false; object->locked = false;
} }

View File

@@ -1,11 +1,12 @@
void ProgressBar::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) { void ProgressBar::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) {
object->widget = gtk_progress_bar_new(); object->widget = gtk_progress_bar_new();
widget->parent = &parent;
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y); gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
void ProgressBar::setProgress(unsigned progress) { void ProgressBar::setPosition(unsigned position) {
progress = progress <= 100 ? progress : 0; position = position <= 100 ? position : 0;
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(object->widget), (double)progress / 100.0); gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(object->widget), (double)position / 100.0);
} }

View File

@@ -2,10 +2,11 @@ static void RadioBox_tick(RadioBox *self) {
if(self->onTick && self->checked() && self->object->locked == false) self->onTick(); if(self->onTick && self->checked() && self->object->locked == false) self->onTick();
} }
void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
first = this; first = this;
object->parentWindow = &parent; object->parentWindow = &parent;
object->widget = gtk_radio_button_new_with_label(0, text); object->widget = gtk_radio_button_new_with_label(0, text);
widget->parent = &parent;
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(RadioBox_tick), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(RadioBox_tick), (gpointer)this);
if(parent.window->defaultFont) setFont(*parent.window->defaultFont); if(parent.window->defaultFont) setFont(*parent.window->defaultFont);
@@ -13,7 +14,7 @@ void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, un
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }
void RadioBox::create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void RadioBox::create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
first = parent.first; first = parent.first;
object->parentWindow = parent.object->parentWindow; object->parentWindow = parent.object->parentWindow;
object->widget = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(parent.object->widget), text); object->widget = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(parent.object->widget), text);

View File

@@ -1,11 +1,17 @@
static void TextBox_activate(TextBox *self) {
if(self->onActivate) self->onActivate();
}
static void TextBox_change(TextBox *self) { static void TextBox_change(TextBox *self) {
if(self->object->locked == false && self->onChange) self->onChange(); if(self->object->locked == false && self->onChange) self->onChange();
} }
void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
object->widget = gtk_entry_new(); object->widget = gtk_entry_new();
widget->parent = &parent;
gtk_entry_set_text(GTK_ENTRY(object->widget), text); gtk_entry_set_text(GTK_ENTRY(object->widget), text);
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
g_signal_connect_swapped(G_OBJECT(object->widget), "activate", G_CALLBACK(TextBox_activate), (gpointer)this);
g_signal_connect_swapped(G_OBJECT(object->widget), "changed", G_CALLBACK(TextBox_change), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "changed", G_CALLBACK(TextBox_change), (gpointer)this);
if(parent.window->defaultFont) setFont(*parent.window->defaultFont); if(parent.window->defaultFont) setFont(*parent.window->defaultFont);
gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y); gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y);
@@ -20,7 +26,7 @@ string TextBox::text() {
return gtk_entry_get_text(GTK_ENTRY(object->widget)); return gtk_entry_get_text(GTK_ENTRY(object->widget));
} }
void TextBox::setText(const char *text) { void TextBox::setText(const string &text) {
object->locked = true; object->locked = true;
gtk_entry_set_text(GTK_ENTRY(object->widget), text); gtk_entry_set_text(GTK_ENTRY(object->widget), text);
object->locked = false; object->locked = false;

View File

@@ -8,6 +8,7 @@ void VerticalSlider::create(Window &parent, unsigned x, unsigned y, unsigned wid
object->position = 0; object->position = 0;
length += (length == 0); length += (length == 0);
object->widget = gtk_vscale_new_with_range(0, length - 1, 1); object->widget = gtk_vscale_new_with_range(0, length - 1, 1);
widget->parent = &parent;
gtk_scale_set_draw_value(GTK_SCALE(object->widget), false); gtk_scale_set_draw_value(GTK_SCALE(object->widget), false);
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
g_signal_connect_swapped(G_OBJECT(object->widget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->widget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)this);

View File

@@ -1,7 +1,16 @@
void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) { void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) {
object->widget = gtk_drawing_area_new(); object->widget = gtk_drawing_area_new();
gtk_widget_set_double_buffered(object->widget, false); widget->parent = &parent;
//gtk_widget_set_double_buffered(object->widget, false);
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
GdkColor color;
color.pixel = 0;
color.red = 0;
color.green = 0;
color.blue = 0;
gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color);
gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y); gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y);
gtk_widget_show(object->widget); gtk_widget_show(object->widget);
} }

View File

@@ -34,3 +34,14 @@ void Widget::setFocused() {
if(visible() == false) setVisible(true); if(visible() == false) setVisible(true);
gtk_widget_grab_focus(object->widget); gtk_widget_grab_focus(object->widget);
} }
void Widget::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
if(widget->parent == 0) return;
gtk_fixed_move(GTK_FIXED(widget->parent->object->formContainer), object->widget, x, y);
gtk_widget_set_size_request(object->widget, width, height);
}
Widget::Widget() {
widget = new Widget::Data;
widget->parent = 0;
}

View File

@@ -7,7 +7,7 @@ static gint Window_close(Window *window) {
return true; return true;
} }
void Window::create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void Window::create(unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
object->widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); object->widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_move(GTK_WINDOW(object->widget), x, y); gtk_window_move(GTK_WINDOW(object->widget), x, y);
@@ -47,6 +47,13 @@ void Window::setFocused() {
gtk_window_present(GTK_WINDOW(object->widget)); gtk_window_present(GTK_WINDOW(object->widget));
} }
Geometry Window::geometry() {
gint x, y, width, height;
gtk_window_get_position(GTK_WINDOW(object->widget), &x, &y);
gtk_widget_get_size_request(object->formContainer, &width, &height);
return Geometry(x, y, width, height);
}
void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) { void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
gtk_window_move(GTK_WINDOW(object->widget), x, y); gtk_window_move(GTK_WINDOW(object->widget), x, y);
gtk_widget_set_size_request(object->formContainer, width, height); gtk_widget_set_size_request(object->formContainer, width, height);
@@ -69,11 +76,11 @@ void Window::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color); gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color);
} }
void Window::setTitle(const char *text) { void Window::setTitle(const string &text) {
gtk_window_set_title(GTK_WINDOW(object->widget), text); gtk_window_set_title(GTK_WINDOW(object->widget), text);
} }
void Window::setStatusText(const char *text) { void Window::setStatusText(const string &text) {
gtk_statusbar_pop(GTK_STATUSBAR(object->status), 1); gtk_statusbar_pop(GTK_STATUSBAR(object->status), 1);
gtk_statusbar_push(GTK_STATUSBAR(object->status), 1, text); gtk_statusbar_push(GTK_STATUSBAR(object->status), 1, text);
} }

View File

@@ -1,7 +1,7 @@
void Button::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void Button::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
button->setParent(parent.window->container); button->setParent(parent.window->container);
button->setGeometry(x, y, width, height); button->setGeometry(x, y, width, height);
button->setText(text); button->setText(QString::fromUtf8(text));
if(parent.window->defaultFont) button->setFont(*parent.window->defaultFont); if(parent.window->defaultFont) button->setFont(*parent.window->defaultFont);
button->show(); button->show();
button->connect(button, SIGNAL(released()), SLOT(onTick())); button->connect(button, SIGNAL(released()), SLOT(onTick()));

View File

@@ -1,7 +1,7 @@
void CheckBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void CheckBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
checkBox->setParent(parent.window->container); checkBox->setParent(parent.window->container);
checkBox->setGeometry(x, y, width, height); checkBox->setGeometry(x, y, width, height);
checkBox->setText(text); checkBox->setText(QString::fromUtf8(text));
if(parent.window->defaultFont) checkBox->setFont(*parent.window->defaultFont); if(parent.window->defaultFont) checkBox->setFont(*parent.window->defaultFont);
checkBox->show(); checkBox->show();
checkBox->connect(checkBox, SIGNAL(stateChanged(int)), SLOT(onTick())); checkBox->connect(checkBox, SIGNAL(stateChanged(int)), SLOT(onTick()));

View File

@@ -1,11 +1,11 @@
void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
comboBox->setParent(parent.window->container); comboBox->setParent(parent.window->container);
comboBox->setGeometry(x, y, width, height); comboBox->setGeometry(x, y, width, height);
if(*text) { if(*text) {
lstring list; lstring list;
list.split("\n", text); list.split("\n", text);
foreach(item, list) addItem((const char*)item); foreach(item, list) addItem(item);
} }
comboBox->connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(onChange())); comboBox->connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(onChange()));
@@ -17,8 +17,8 @@ void ComboBox::reset() {
while(comboBox->count()) comboBox->removeItem(0); while(comboBox->count()) comboBox->removeItem(0);
} }
void ComboBox::addItem(const char *text) { void ComboBox::addItem(const string &text) {
comboBox->addItem(text); comboBox->addItem(QString::fromUtf8(text));
} }
unsigned ComboBox::selection() { unsigned ComboBox::selection() {
@@ -27,7 +27,9 @@ unsigned ComboBox::selection() {
} }
void ComboBox::setSelection(unsigned row) { void ComboBox::setSelection(unsigned row) {
object->locked = true;
comboBox->setCurrentIndex(row); comboBox->setCurrentIndex(row);
object->locked = false;
} }
ComboBox::ComboBox() { ComboBox::ComboBox() {

View File

@@ -1,13 +1,14 @@
void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
editBox->setParent(parent.window->container); editBox->setParent(parent.window->container);
editBox->setGeometry(x, y, width, height); editBox->setGeometry(x, y, width, height);
editBox->setText(text); editBox->setPlainText(QString::fromUtf8(text));
if(parent.window->defaultFont) editBox->setFont(*parent.window->defaultFont); if(parent.window->defaultFont) editBox->setFont(*parent.window->defaultFont);
editBox->show(); editBox->show();
editBox->connect(editBox, SIGNAL(textChanged()), SLOT(onChange())); editBox->connect(editBox, SIGNAL(textChanged()), SLOT(onChange()));
} }
void EditBox::setEditable(bool editable) { void EditBox::setEditable(bool editable) {
editBox->setReadOnly(editable == false);
} }
void EditBox::setWordWrap(bool wordWrap) { void EditBox::setWordWrap(bool wordWrap) {
@@ -15,9 +16,11 @@ void EditBox::setWordWrap(bool wordWrap) {
} }
string EditBox::text() { string EditBox::text() {
return editBox->toPlainText().toUtf8().constData();
} }
void EditBox::setText(const char *text) { void EditBox::setText(const string &text) {
editBox->setPlainText(QString::fromUtf8(text));
} }
EditBox::EditBox() { EditBox::EditBox() {

View File

@@ -1,5 +1,5 @@
bool Font::create(const char *name, unsigned size, Font::Style style) { bool Font::create(const string &name, unsigned size, Font::Style style) {
font->setFamily(name); font->setFamily(QString::fromUtf8(name));
font->setPointSize(size); font->setPointSize(size);
font->setBold((style & Style::Bold) == Style::Bold); font->setBold((style & Style::Bold) == Style::Bold);
font->setItalic((style & Style::Italic) == Style::Italic); font->setItalic((style & Style::Italic) == Style::Italic);

View File

@@ -1,13 +1,13 @@
void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
label->setParent(parent.window->container); label->setParent(parent.window->container);
label->setGeometry(x, y, width, height); label->setGeometry(x, y, width, height);
label->setText(text); label->setText(QString::fromUtf8(text));
if(parent.window->defaultFont) label->setFont(*parent.window->defaultFont); if(parent.window->defaultFont) label->setFont(*parent.window->defaultFont);
label->show(); label->show();
} }
void Label::setText(const char *text) { void Label::setText(const string &text) {
label->setText(text); label->setText(QString::fromUtf8(text));
} }
Label::Label() { Label::Label() {

View File

@@ -1,4 +1,4 @@
void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
listBox->setParent(parent.window->container); listBox->setParent(parent.window->container);
listBox->setGeometry(x, y, width, height); listBox->setGeometry(x, y, width, height);
listBox->setAllColumnsShowFocus(true); listBox->setAllColumnsShowFocus(true);
@@ -7,7 +7,7 @@ void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
QStringList labels; QStringList labels;
foreach(item, list) labels << (const char*)item; foreach(item, list) labels << QString::fromUtf8(item);
listBox->setColumnCount(list.size()); listBox->setColumnCount(list.size());
listBox->setHeaderLabels(labels); listBox->setHeaderLabels(labels);
for(unsigned i = 0; i < list.size(); i++) listBox->resizeColumnToContents(i); for(unsigned i = 0; i < list.size(); i++) listBox->resizeColumnToContents(i);
@@ -16,6 +16,7 @@ void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
listBox->setAlternatingRowColors(list.size() >= 2); listBox->setAlternatingRowColors(list.size() >= 2);
listBox->connect(listBox, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate())); listBox->connect(listBox, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate()));
listBox->connect(listBox, SIGNAL(itemSelectionChanged()), SLOT(onChange())); listBox->connect(listBox, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
listBox->connect(listBox, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onTick(QTreeWidgetItem*)));
if(parent.window->defaultFont) listBox->setFont(*parent.window->defaultFont); if(parent.window->defaultFont) listBox->setFont(*parent.window->defaultFont);
listBox->show(); listBox->show();
} }
@@ -24,6 +25,14 @@ void ListBox::setHeaderVisible(bool headerVisible) {
listBox->setHeaderHidden(headerVisible == false); listBox->setHeaderHidden(headerVisible == false);
} }
void ListBox::setCheckable(bool checkable) {
listBox->checkable = checkable;
if(listBox->checkable) {
auto items = listBox->findItems("", Qt::MatchContains);
for(unsigned i = 0; i < items.size(); i++) items[i]->setCheckState(0, Qt::Unchecked);
}
}
void ListBox::reset() { void ListBox::reset() {
listBox->clear(); listBox->clear();
} }
@@ -32,20 +41,37 @@ void ListBox::resizeColumnsToContent() {
for(unsigned i = 0; i < listBox->columnCount(); i++) listBox->resizeColumnToContents(i); for(unsigned i = 0; i < listBox->columnCount(); i++) listBox->resizeColumnToContents(i);
} }
void ListBox::addItem(const char *text) { void ListBox::addItem(const string &text) {
object->locked = true;
auto items = listBox->findItems("", Qt::MatchContains); auto items = listBox->findItems("", Qt::MatchContains);
QTreeWidgetItem *item = new QTreeWidgetItem(listBox); QTreeWidgetItem *item = new QTreeWidgetItem(listBox);
if(listBox->checkable) item->setCheckState(0, Qt::Unchecked);
item->setData(0, Qt::UserRole, (unsigned)items.size()); item->setData(0, Qt::UserRole, (unsigned)items.size());
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) item->setText(i, (const char*)list[i]); for(unsigned i = 0; i < list.size(); i++) item->setText(i, QString::fromUtf8(list[i]));
object->locked = false;
} }
void ListBox::setItem(unsigned row, const char *text) { void ListBox::setItem(unsigned row, const string &text) {
object->locked = true;
QTreeWidgetItem *item = listBox->topLevelItem(row); QTreeWidgetItem *item = listBox->topLevelItem(row);
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) item->setText(i, (const char*)list[i]); for(unsigned i = 0; i < list.size(); i++) item->setText(i, QString::fromUtf8(list[i]));
object->locked = false;
}
bool ListBox::checked(unsigned row) {
QTreeWidgetItem *item = listBox->topLevelItem(row);
return (item ? item->checkState(0) == Qt::Checked : false);
}
void ListBox::setChecked(unsigned row, bool checked) {
object->locked = true;
QTreeWidgetItem *item = listBox->topLevelItem(row);
if(item) item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
object->locked = false;
} }
optional<unsigned> ListBox::selection() { optional<unsigned> ListBox::selection() {

View File

@@ -1,10 +1,14 @@
void Menu::create(Window &parent, const char *text) { void Menu::create(Window &parent, const string &text) {
menu->setTitle(text); menu->parent = &parent;
if(menu->parent->window->defaultFont) menu->setFont(*menu->parent->window->defaultFont);
menu->setTitle(QString::fromUtf8(text));
parent.window->menuBar->addMenu(menu); parent.window->menuBar->addMenu(menu);
} }
void Menu::create(Menu &parent, const char *text) { void Menu::create(Menu &parent, const string &text) {
menu->setTitle(text); menu->parent = parent.menu->parent;
if(menu->parent->window->defaultFont) menu->setFont(*menu->parent->window->defaultFont);
menu->setTitle(QString::fromUtf8(text));
parent.menu->addMenu(menu); parent.menu->addMenu(menu);
} }
@@ -52,8 +56,8 @@ MenuSeparator::MenuSeparator() {
menuSeparator = new MenuSeparator::Data(*this); menuSeparator = new MenuSeparator::Data(*this);
} }
void MenuItem::create(Menu &parent, const char *text) { void MenuItem::create(Menu &parent, const string &text) {
menuItem->setText(text); menuItem->setText(QString::fromUtf8(text));
menuItem->connect(menuItem, SIGNAL(triggered()), SLOT(onTick())); menuItem->connect(menuItem, SIGNAL(triggered()), SLOT(onTick()));
parent.menu->addAction(menuItem); parent.menu->addAction(menuItem);
} }
@@ -78,8 +82,8 @@ MenuItem::MenuItem() {
menuItem = new MenuItem::Data(*this); menuItem = new MenuItem::Data(*this);
} }
void MenuCheckItem::create(Menu &parent, const char *text) { void MenuCheckItem::create(Menu &parent, const string &text) {
menuCheckItem->setText(text); menuCheckItem->setText(QString::fromUtf8(text));
menuCheckItem->setCheckable(true); menuCheckItem->setCheckable(true);
menuCheckItem->connect(menuCheckItem, SIGNAL(triggered()), SLOT(onTick())); menuCheckItem->connect(menuCheckItem, SIGNAL(triggered()), SLOT(onTick()));
parent.menu->addAction(menuCheckItem); parent.menu->addAction(menuCheckItem);
@@ -113,22 +117,22 @@ MenuCheckItem::MenuCheckItem() {
menuCheckItem = new MenuCheckItem::Data(*this); menuCheckItem = new MenuCheckItem::Data(*this);
} }
void MenuRadioItem::create(Menu &parent, const char *text) { void MenuRadioItem::create(Menu &parent, const string &text) {
menuRadioItem->parent = &parent; menuRadioItem->parent = &parent;
menuRadioItem->actionGroup = new QActionGroup(0); menuRadioItem->actionGroup = new QActionGroup(0);
menuRadioItem->actionGroup->addAction(menuRadioItem); menuRadioItem->actionGroup->addAction(menuRadioItem);
menuRadioItem->setText(text); menuRadioItem->setText(QString::fromUtf8(text));
menuRadioItem->setCheckable(true); menuRadioItem->setCheckable(true);
menuRadioItem->setChecked(true); menuRadioItem->setChecked(true);
menuRadioItem->connect(menuRadioItem, SIGNAL(changed()), SLOT(onTick())); menuRadioItem->connect(menuRadioItem, SIGNAL(changed()), SLOT(onTick()));
menuRadioItem->parent->menu->addAction(menuRadioItem); menuRadioItem->parent->menu->addAction(menuRadioItem);
} }
void MenuRadioItem::create(MenuRadioItem &parent, const char *text) { void MenuRadioItem::create(MenuRadioItem &parent, const string &text) {
menuRadioItem->parent = parent.menuRadioItem->parent; menuRadioItem->parent = parent.menuRadioItem->parent;
menuRadioItem->actionGroup = parent.menuRadioItem->actionGroup; menuRadioItem->actionGroup = parent.menuRadioItem->actionGroup;
menuRadioItem->actionGroup->addAction(menuRadioItem); menuRadioItem->actionGroup->addAction(menuRadioItem);
menuRadioItem->setText(text); menuRadioItem->setText(QString::fromUtf8(text));
menuRadioItem->setCheckable(true); menuRadioItem->setCheckable(true);
menuRadioItem->connect(menuRadioItem, SIGNAL(changed()), SLOT(onTick())); menuRadioItem->connect(menuRadioItem, SIGNAL(changed()), SLOT(onTick()));
menuRadioItem->parent->menu->addAction(menuRadioItem); menuRadioItem->parent->menu->addAction(menuRadioItem);

View File

@@ -16,26 +16,30 @@ static MessageWindow::Response MessageWindow_response(MessageWindow::Buttons but
return MessageWindow::Response::Ok; return MessageWindow::Response::Ok;
} }
MessageWindow::Response MessageWindow::information(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) {
return MessageWindow_response( return MessageWindow_response(
buttons, QMessageBox::information(&parent != &Window::None ? parent.window : 0, " ", text, MessageWindow_buttons(buttons)) buttons, QMessageBox::information(&parent != &Window::None ? parent.window : 0, " ",
QString::fromUtf8(text), MessageWindow_buttons(buttons))
); );
} }
MessageWindow::Response MessageWindow::question(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) {
return MessageWindow_response( return MessageWindow_response(
buttons, QMessageBox::question(&parent != &Window::None ? parent.window : 0, " ", text, MessageWindow_buttons(buttons)) buttons, QMessageBox::question(&parent != &Window::None ? parent.window : 0, " ",
QString::fromUtf8(text), MessageWindow_buttons(buttons))
); );
} }
MessageWindow::Response MessageWindow::warning(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) {
return MessageWindow_response( return MessageWindow_response(
buttons, QMessageBox::warning(&parent != &Window::None ? parent.window : 0, " ", text, MessageWindow_buttons(buttons)) buttons, QMessageBox::warning(&parent != &Window::None ? parent.window : 0, " ",
QString::fromUtf8(text), MessageWindow_buttons(buttons))
); );
} }
MessageWindow::Response MessageWindow::critical(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) {
return MessageWindow_response( return MessageWindow_response(
buttons, QMessageBox::critical(&parent != &Window::None ? parent.window : 0, " ", text, MessageWindow_buttons(buttons)) buttons, QMessageBox::critical(&parent != &Window::None ? parent.window : 0, " ",
QString::fromUtf8(text), MessageWindow_buttons(buttons))
); );
} }

View File

@@ -2,5 +2,6 @@ void Object::unused() {
} }
Object::Object() { Object::Object() {
OS::initialize();
object = new Object::Data(*this); object = new Object::Data(*this);
} }

View File

@@ -6,8 +6,8 @@ void ProgressBar::create(Window &parent, unsigned x, unsigned y, unsigned width,
progressBar->show(); progressBar->show();
} }
void ProgressBar::setProgress(unsigned progress) { void ProgressBar::setPosition(unsigned position) {
progressBar->setValue(progress); progressBar->setValue(position);
} }
ProgressBar::ProgressBar() { ProgressBar::ProgressBar() {

View File

@@ -27,12 +27,22 @@ namespace phoenix {
#include "viewport.cpp" #include "viewport.cpp"
#include "messagewindow.cpp" #include "messagewindow.cpp"
OS &os = OS::handle(); OS::Data *OS::os = 0;
Window Window::None; Window Window::None;
OS& OS::handle() { void OS::initialize() {
static OS os; static bool initialized = false;
return os; if(initialized == true) return;
initialized = true;
os = new OS::Data;
static int argc = 1;
static char *argv[2];
argv[0] = new char[8];
argv[1] = 0;
strcpy(argv[0], "phoenix");
char **argvp = argv;
os->application = new QApplication(argc, argvp);
} }
bool OS::pending() { bool OS::pending() {
@@ -59,14 +69,17 @@ unsigned OS::desktopHeight() {
return QApplication::desktop()->screenGeometry().height(); return QApplication::desktop()->screenGeometry().height();
} }
string OS::folderSelect(Window &parent, const char *path) { string OS::folderSelect(Window &parent, const string &path) {
QString directory = QFileDialog::getExistingDirectory( QString directory = QFileDialog::getExistingDirectory(
&parent != &Window::None ? parent.window : 0, "Select Directory", path, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks &parent != &Window::None ? parent.window : 0, "Select Directory",
QString::fromUtf8(path), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
); );
return directory.toUtf8().constData(); string name = directory.toUtf8().constData();
if(name.endswith("/") == false) name.append("/");
return name;
} }
string OS::fileOpen(Window &parent, const char *filter, const char *path) { string OS::fileOpen(Window &parent, const string &filter, const string &path) {
string filters; string filters;
lstring list; lstring list;
list.split("\n", filter); list.split("\n", filter);
@@ -83,12 +96,13 @@ string OS::fileOpen(Window &parent, const char *filter, const char *path) {
filters.rtrim(";;"); filters.rtrim(";;");
QString filename = QFileDialog::getOpenFileName( QString filename = QFileDialog::getOpenFileName(
&parent != &Window::None ? parent.window : 0, "Open File", path, (const char*)filters &parent != &Window::None ? parent.window : 0, "Open File",
QString::fromUtf8(path), QString::fromUtf8(filters)
); );
return filename.toUtf8().constData(); return filename.toUtf8().constData();
} }
string OS::fileSave(Window &parent, const char *filter, const char *path) { string OS::fileSave(Window &parent, const string &filter, const string &path) {
string filters; string filters;
lstring list; lstring list;
list.split("\n", filter); list.split("\n", filter);
@@ -105,20 +119,10 @@ string OS::fileSave(Window &parent, const char *filter, const char *path) {
filters.rtrim(";;"); filters.rtrim(";;");
QString filename = QFileDialog::getSaveFileName( QString filename = QFileDialog::getSaveFileName(
&parent != &Window::None ? parent.window : 0, "Save File", path, (const char*)filters &parent != &Window::None ? parent.window : 0, "Save File",
QString::fromUtf8(path), QString::fromUtf8(filters)
); );
return filename.toUtf8().constData(); return filename.toUtf8().constData();
} }
OS::OS() {
os = new OS::Data(*this);
static int argc = 1;
static char *argv[2];
argv[0] = new char[8];
argv[1] = 0;
strcpy(argv[0], "phoenix");
char **argvp = argv;
os->application = new QApplication(argc, argvp);
}
} }

View File

@@ -12,13 +12,20 @@ struct Object {
Data *object; Data *object;
}; };
struct Geometry {
unsigned x, y;
unsigned width, height;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(unsigned x, unsigned y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
};
struct Font : Object { struct Font : Object {
enum class Style : unsigned { enum class Style : unsigned {
None = 0, None = 0,
Bold = 1, Bold = 1,
Italic = 2, Italic = 2,
}; };
bool create(const char *name, unsigned size, Font::Style style = Style::None); bool create(const nall::string &name, unsigned size, Font::Style style = Style::None);
Font(); Font();
~Font(); ~Font();
//private: //private:
@@ -37,8 +44,8 @@ struct Action : Object {
}; };
struct Menu : Action { struct Menu : Action {
void create(Window &parent, const char *text); void create(Window &parent, const nall::string &text);
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
bool visible(); bool visible();
void setVisible(bool visible = true); void setVisible(bool visible = true);
bool enabled(); bool enabled();
@@ -63,7 +70,7 @@ struct MenuSeparator : Action {
struct MenuItem : Action { struct MenuItem : Action {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
bool visible(); bool visible();
void setVisible(bool visible = true); void setVisible(bool visible = true);
bool enabled(); bool enabled();
@@ -76,7 +83,7 @@ struct MenuItem : Action {
struct MenuCheckItem : Action { struct MenuCheckItem : Action {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
bool visible(); bool visible();
void setVisible(bool visible = true); void setVisible(bool visible = true);
bool enabled(); bool enabled();
@@ -91,8 +98,8 @@ struct MenuCheckItem : Action {
struct MenuRadioItem : Action { struct MenuRadioItem : Action {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
void create(MenuRadioItem &parent, const char *text); void create(MenuRadioItem &parent, const nall::string &text);
bool visible(); bool visible();
void setVisible(bool visible = true); void setVisible(bool visible = true);
bool enabled(); bool enabled();
@@ -112,8 +119,8 @@ struct Widget : Object {
void setVisible(bool visible = true); void setVisible(bool visible = true);
bool enabled(); bool enabled();
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
bool focused(); virtual bool focused();
void setFocused(); virtual void setFocused();
Widget(); Widget();
//private: //private:
struct Data; struct Data;
@@ -121,26 +128,28 @@ struct Widget : Object {
}; };
struct Window : Widget { struct Window : Widget {
static Window None;
nall::function<bool ()> onClose; nall::function<bool ()> onClose;
void create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
Geometry geometry();
void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height); void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
void setDefaultFont(Font &font); void setDefaultFont(Font &font);
void setFont(Font &font); void setFont(Font &font);
void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue); void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
void setTitle(const char *text); void setTitle(const nall::string &text);
void setStatusText(const char *text); void setStatusText(const nall::string &text);
void setMenuVisible(bool visible = true); void setMenuVisible(bool visible = true);
void setStatusVisible(bool visible = true); void setStatusVisible(bool visible = true);
bool focused();
Window(); Window();
//private: //private:
struct Data; struct Data;
Data *window; Data *window;
static Window None;
}; };
struct Button : Widget { struct Button : Widget {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
Button(); Button();
//private: //private:
struct Data; struct Data;
@@ -161,7 +170,7 @@ struct Canvas : Widget {
struct CheckBox : Widget { struct CheckBox : Widget {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
bool checked(); bool checked();
void setChecked(bool checked = true); void setChecked(bool checked = true);
CheckBox(); CheckBox();
@@ -172,9 +181,9 @@ struct CheckBox : Widget {
struct ComboBox : Widget { struct ComboBox : Widget {
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void reset(); void reset();
void addItem(const char *text); void addItem(const nall::string &text);
unsigned selection(); unsigned selection();
void setSelection(unsigned row); void setSelection(unsigned row);
ComboBox(); ComboBox();
@@ -185,11 +194,11 @@ struct ComboBox : Widget {
struct EditBox : Widget { struct EditBox : Widget {
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setEditable(bool editable = true); void setEditable(bool editable = true);
void setWordWrap(bool wordWrap = true); void setWordWrap(bool wordWrap = true);
nall::string text(); nall::string text();
void setText(const char *text); void setText(const nall::string &text);
EditBox(); EditBox();
//private: //private:
struct Data; struct Data;
@@ -208,8 +217,8 @@ struct HorizontalSlider : Widget {
}; };
struct Label : Widget { struct Label : Widget {
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setText(const char *text); void setText(const nall::string &text);
Label(); Label();
//private: //private:
struct Data; struct Data;
@@ -219,12 +228,16 @@ struct Label : Widget {
struct ListBox : Widget { struct ListBox : Widget {
nall::function<void ()> onActivate; nall::function<void ()> onActivate;
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); nall::function<void (unsigned)> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setHeaderVisible(bool headerVisible = true); void setHeaderVisible(bool headerVisible = true);
void setCheckable(bool checkable = true);
void reset(); void reset();
void resizeColumnsToContent(); void resizeColumnsToContent();
void addItem(const char *text); void addItem(const nall::string &text);
void setItem(unsigned row, const char *text); void setItem(unsigned row, const nall::string &text);
bool checked(unsigned row);
void setChecked(unsigned row, bool checked = true);
nall::optional<unsigned> selection(); nall::optional<unsigned> selection();
void setSelection(unsigned row); void setSelection(unsigned row);
ListBox(); ListBox();
@@ -235,7 +248,7 @@ struct ListBox : Widget {
struct ProgressBar : Widget { struct ProgressBar : Widget {
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height);
void setProgress(unsigned progress); void setPosition(unsigned position);
ProgressBar(); ProgressBar();
//private: //private:
struct Data; struct Data;
@@ -244,8 +257,8 @@ struct ProgressBar : Widget {
struct RadioBox : Widget { struct RadioBox : Widget {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
bool checked(); bool checked();
void setChecked(); void setChecked();
RadioBox(); RadioBox();
@@ -255,11 +268,12 @@ struct RadioBox : Widget {
}; };
struct TextBox : Widget { struct TextBox : Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setEditable(bool editable = true); void setEditable(bool editable = true);
nall::string text(); nall::string text();
void setText(const char *text); void setText(const nall::string &text);
TextBox(); TextBox();
//private: //private:
struct Data; struct Data;
@@ -298,30 +312,26 @@ struct MessageWindow : Object {
Yes, Yes,
No, No,
}; };
static Response information(Window &parent, const char *text, Buttons = Buttons::Ok); static Response information(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response question(Window &parent, const char *text, Buttons = Buttons::YesNo); static Response question(Window &parent, const nall::string &text, Buttons = Buttons::YesNo);
static Response warning(Window &parent, const char *text, Buttons = Buttons::Ok); static Response warning(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response critical(Window &parent, const char *text, Buttons = Buttons::Ok); static Response critical(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
}; };
struct OS : Object { struct OS : Object {
bool pending(); static bool pending();
void run(); static void run();
void main(); static void main();
void quit(); static void quit();
unsigned desktopWidth(); static unsigned desktopWidth();
unsigned desktopHeight(); static unsigned desktopHeight();
nall::string folderSelect(Window &parent, const char *path = ""); static nall::string folderSelect(Window &parent, const nall::string &path = "");
nall::string fileOpen(Window &parent, const char *filter, const char *path = ""); static nall::string fileOpen(Window &parent, const nall::string &filter, const nall::string &path = "");
nall::string fileSave(Window &parent, const char *filter, const char *path = ""); static nall::string fileSave(Window &parent, const nall::string &filter, const nall::string &path = "");
//private: //private:
static OS& handle();
struct Data; struct Data;
Data *os; static Data *os;
private: static void initialize();
OS();
}; };
extern OS &os;
} }

View File

@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
** Meta object code from reading C++ file 'qt.moc.hpp' ** Meta object code from reading C++ file 'qt.moc.hpp'
** **
** Created: Sat Sep 25 06:31:14 2010 ** Created: Mon Oct 11 13:03:04 2010
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2) ** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2)
** **
** WARNING! All changes made in this file will be lost! ** WARNING! All changes made in this file will be lost!
@@ -641,7 +641,7 @@ static const uint qt_meta_data_ListBox__Data[] = {
4, // revision 4, // revision
0, // classname 0, // classname
0, 0, // classinfo 0, 0, // classinfo
2, 14, // methods 3, 14, // methods
0, 0, // properties 0, 0, // properties
0, 0, // enums/sets 0, 0, // enums/sets
0, 0, // constructors 0, 0, // constructors
@@ -651,12 +651,14 @@ static const uint qt_meta_data_ListBox__Data[] = {
// slots: signature, parameters, type, tag, flags // slots: signature, parameters, type, tag, flags
15, 14, 14, 14, 0x0a, 15, 14, 14, 14, 0x0a,
28, 14, 14, 14, 0x0a, 28, 14, 14, 14, 0x0a,
44, 39, 14, 14, 0x0a,
0 // eod 0 // eod
}; };
static const char qt_meta_stringdata_ListBox__Data[] = { static const char qt_meta_stringdata_ListBox__Data[] = {
"ListBox::Data\0\0onActivate()\0onChange()\0" "ListBox::Data\0\0onActivate()\0onChange()\0"
"item\0onTick(QTreeWidgetItem*)\0"
}; };
const QMetaObject ListBox::Data::staticMetaObject = { const QMetaObject ListBox::Data::staticMetaObject = {
@@ -690,9 +692,10 @@ int ListBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
switch (_id) { switch (_id) {
case 0: onActivate(); break; case 0: onActivate(); break;
case 1: onChange(); break; case 1: onChange(); break;
case 2: onTick((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break;
default: ; default: ;
} }
_id -= 2; _id -= 3;
} }
return _id; return _id;
} }
@@ -761,7 +764,7 @@ static const uint qt_meta_data_TextBox__Data[] = {
4, // revision 4, // revision
0, // classname 0, // classname
0, 0, // classinfo 0, 0, // classinfo
1, 14, // methods 2, 14, // methods
0, 0, // properties 0, 0, // properties
0, 0, // enums/sets 0, 0, // enums/sets
0, 0, // constructors 0, 0, // constructors
@@ -770,12 +773,13 @@ static const uint qt_meta_data_TextBox__Data[] = {
// slots: signature, parameters, type, tag, flags // slots: signature, parameters, type, tag, flags
15, 14, 14, 14, 0x0a, 15, 14, 14, 14, 0x0a,
28, 14, 14, 14, 0x0a,
0 // eod 0 // eod
}; };
static const char qt_meta_stringdata_TextBox__Data[] = { static const char qt_meta_stringdata_TextBox__Data[] = {
"TextBox::Data\0\0onChange()\0" "TextBox::Data\0\0onActivate()\0onChange()\0"
}; };
const QMetaObject TextBox::Data::staticMetaObject = { const QMetaObject TextBox::Data::staticMetaObject = {
@@ -807,10 +811,11 @@ int TextBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
return _id; return _id;
if (_c == QMetaObject::InvokeMetaMethod) { if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) { switch (_id) {
case 0: onChange(); break; case 0: onActivate(); break;
case 1: onChange(); break;
default: ; default: ;
} }
_id -= 1; _id -= 2;
} }
return _id; return _id;
} }

View File

@@ -19,8 +19,9 @@ public:
struct Menu::Data : public QMenu { struct Menu::Data : public QMenu {
public: public:
Menu &self; Menu &self;
Window *parent;
Data(Menu &self) : self(self) { Data(Menu &self) : self(self), parent(0) {
} }
}; };
@@ -164,7 +165,7 @@ public:
public slots: public slots:
void onChange() { void onChange() {
if(self.onChange) self.onChange(); if(self.object->locked == false && self.onChange) self.onChange();
} }
}; };
@@ -213,8 +214,10 @@ struct ListBox::Data : public QTreeWidget {
public: public:
ListBox &self; ListBox &self;
bool checkable;
Data(ListBox &self) : self(self) { Data(ListBox &self) : self(self) {
checkable = false;
} }
public slots: public slots:
@@ -225,6 +228,10 @@ public slots:
void onChange() { void onChange() {
if(self.object->locked == false && self.onChange) self.onChange(); if(self.object->locked == false && self.onChange) self.onChange();
} }
void onTick(QTreeWidgetItem *item) {
if(self.object->locked == false && self.onTick) self.onTick(item->data(0, Qt::UserRole).toUInt());
}
}; };
struct ProgressBar::Data : public QProgressBar { struct ProgressBar::Data : public QProgressBar {
@@ -262,6 +269,10 @@ public:
} }
public slots: public slots:
void onActivate() {
if(self.onActivate) self.onActivate();
}
void onChange() { void onChange() {
if(self.onChange) self.onChange(); if(self.onChange) self.onChange();
} }
@@ -294,11 +305,7 @@ struct OS::Data : public QObject {
Q_OBJECT Q_OBJECT
public: public:
OS &self;
QApplication *application; QApplication *application;
Data(OS &self) : self(self) {
}
public slots: public slots:
}; };

View File

@@ -1,23 +1,23 @@
void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
radioBox->parent = &parent; radioBox->parent = &parent;
radioBox->buttonGroup = new QButtonGroup; radioBox->buttonGroup = new QButtonGroup;
radioBox->buttonGroup->addButton(radioBox); radioBox->buttonGroup->addButton(radioBox);
radioBox->setParent(radioBox->parent->window->container); radioBox->setParent(radioBox->parent->window->container);
radioBox->setGeometry(x, y, width, height); radioBox->setGeometry(x, y, width, height);
radioBox->setText(text); radioBox->setText(QString::fromUtf8(text));
radioBox->setChecked(true); radioBox->setChecked(true);
if(parent.window->defaultFont) radioBox->setFont(*parent.window->defaultFont); if(parent.window->defaultFont) radioBox->setFont(*parent.window->defaultFont);
radioBox->show(); radioBox->show();
radioBox->connect(radioBox, SIGNAL(toggled(bool)), SLOT(onTick())); radioBox->connect(radioBox, SIGNAL(toggled(bool)), SLOT(onTick()));
} }
void RadioBox::create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void RadioBox::create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
radioBox->parent = parent.radioBox->parent; radioBox->parent = parent.radioBox->parent;
radioBox->buttonGroup = parent.radioBox->buttonGroup; radioBox->buttonGroup = parent.radioBox->buttonGroup;
radioBox->buttonGroup->addButton(radioBox); radioBox->buttonGroup->addButton(radioBox);
radioBox->setParent(radioBox->parent->window->container); radioBox->setParent(radioBox->parent->window->container);
radioBox->setGeometry(x, y, width, height); radioBox->setGeometry(x, y, width, height);
radioBox->setText(text); radioBox->setText(QString::fromUtf8(text));
if(radioBox->parent->window->defaultFont) radioBox->setFont(*radioBox->parent->window->defaultFont); if(radioBox->parent->window->defaultFont) radioBox->setFont(*radioBox->parent->window->defaultFont);
radioBox->show(); radioBox->show();
radioBox->connect(radioBox, SIGNAL(toggled(bool)), SLOT(onTick())); radioBox->connect(radioBox, SIGNAL(toggled(bool)), SLOT(onTick()));

View File

@@ -1,9 +1,10 @@
void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
textBox->setParent(parent.window->container); textBox->setParent(parent.window->container);
textBox->setGeometry(x, y, width, height); textBox->setGeometry(x, y, width, height);
textBox->setText(text); textBox->setText(QString::fromUtf8(text));
if(parent.window->defaultFont) textBox->setFont(*parent.window->defaultFont); if(parent.window->defaultFont) textBox->setFont(*parent.window->defaultFont);
textBox->show(); textBox->show();
textBox->connect(textBox, SIGNAL(returnPressed()), SLOT(onActivate()));
textBox->connect(textBox, SIGNAL(textEdited(const QString&)), SLOT(onChange())); textBox->connect(textBox, SIGNAL(textEdited(const QString&)), SLOT(onChange()));
} }
@@ -15,8 +16,8 @@ string TextBox::text() {
return textBox->text().toUtf8().constData(); return textBox->text().toUtf8().constData();
} }
void TextBox::setText(const char *text) { void TextBox::setText(const string &text) {
textBox->setText(text); textBox->setText(QString::fromUtf8(text));
} }
TextBox::TextBox() { TextBox::TextBox() {

View File

@@ -1,6 +1,8 @@
void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) { void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) {
viewport->setParent(parent.window->container); viewport->setParent(parent.window->container);
viewport->setGeometry(x, y, width, height); viewport->setGeometry(x, y, width, height);
viewport->setAttribute(Qt::WA_PaintOnScreen, true);
viewport->setStyleSheet("background: #000000");
viewport->show(); viewport->show();
} }

View File

@@ -1,5 +1,5 @@
void Window::create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void Window::create(unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
window->setWindowTitle(text); window->setWindowTitle(QString::fromUtf8(text));
window->move(x, y); window->move(x, y);
window->layout = new QVBoxLayout(window); window->layout = new QVBoxLayout(window);
@@ -23,6 +23,10 @@ void Window::create(unsigned x, unsigned y, unsigned width, unsigned height, con
window->layout->addWidget(window->statusBar); window->layout->addWidget(window->statusBar);
} }
Geometry Window::geometry() {
return Geometry(window->x(), window->y(), window->container->width(), window->container->height());
}
void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) { void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
window->container->setFixedSize(width, height); window->container->setFixedSize(width, height);
window->move(x, y); window->move(x, y);
@@ -44,12 +48,12 @@ void Window::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
window->setAutoFillBackground(true); window->setAutoFillBackground(true);
} }
void Window::setTitle(const char *text) { void Window::setTitle(const string &text) {
window->setWindowTitle(text); window->setWindowTitle(QString::fromUtf8(text));
} }
void Window::setStatusText(const char *text) { void Window::setStatusText(const string &text) {
window->statusBar->showMessage(text, 0); window->statusBar->showMessage(QString::fromUtf8(text), 0);
} }
void Window::setMenuVisible(bool visible) { void Window::setMenuVisible(bool visible) {
@@ -62,6 +66,10 @@ void Window::setStatusVisible(bool visible) {
else window->statusBar->hide(); else window->statusBar->hide();
} }
bool Window::focused() {
return window->isActiveWindow() && !window->isMinimized();
}
Window::Window() { Window::Window() {
window = new Window::Data(*this); window = new Window::Data(*this);
window->defaultFont = 0; window->defaultFont = 0;

View File

@@ -1,4 +1,4 @@
void Button::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void Button::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
widget->window = CreateWindow( widget->window = CreateWindow(
L"BUTTON", utf16_t(text), L"BUTTON", utf16_t(text),
WS_CHILD | WS_TABSTOP | WS_VISIBLE, WS_CHILD | WS_TABSTOP | WS_VISIBLE,
@@ -6,5 +6,5 @@ void Button::create(Window &parent, unsigned x, unsigned y, unsigned width, unsi
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
} }

View File

@@ -1,4 +1,4 @@
void CheckBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void CheckBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
widget->window = CreateWindow( widget->window = CreateWindow(
L"BUTTON", utf16_t(text), L"BUTTON", utf16_t(text),
WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_CHECKBOX, WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_CHECKBOX,
@@ -6,7 +6,7 @@ void CheckBox::create(Window &parent, unsigned x, unsigned y, unsigned width, un
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
} }
bool CheckBox::checked() { bool CheckBox::checked() {

View File

@@ -1,4 +1,4 @@
void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
widget->window = CreateWindowEx( widget->window = CreateWindowEx(
0, L"COMBOBOX", L"", 0, L"COMBOBOX", L"",
WS_CHILD | WS_TABSTOP | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_CHILD | WS_TABSTOP | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
@@ -7,7 +7,7 @@ void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, un
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
//CreateWindow height parameter is the height of the expanded list box; //CreateWindow height parameter is the height of the expanded list box;
//need additional code to override default ComboBox control height //need additional code to override default ComboBox control height
@@ -27,7 +27,7 @@ void ComboBox::reset() {
SendMessage(widget->window, CB_RESETCONTENT, 0, 0); SendMessage(widget->window, CB_RESETCONTENT, 0, 0);
} }
void ComboBox::addItem(const char *text) { void ComboBox::addItem(const string &text) {
SendMessage(widget->window, CB_ADDSTRING, 0, (LPARAM)(wchar_t*)utf16_t(text)); SendMessage(widget->window, CB_ADDSTRING, 0, (LPARAM)(wchar_t*)utf16_t(text));
if(SendMessage(widget->window, CB_GETCOUNT, 0, 0) == 1) setSelection(0); if(SendMessage(widget->window, CB_GETCOUNT, 0, 0) == 1) setSelection(0);
} }

View File

@@ -1,4 +1,4 @@
void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
widget->window = CreateWindowEx( widget->window = CreateWindowEx(
WS_EX_CLIENTEDGE, L"EDIT", L"", WS_EX_CLIENTEDGE, L"EDIT", L"",
WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN | WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN |
@@ -8,7 +8,7 @@ void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
); );
setText(text); setText(text);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
} }
string EditBox::getText() { string EditBox::getText() {
@@ -21,7 +21,7 @@ string EditBox::getText() {
return text; return text;
} }
void EditBox::setText(const char *text) { void EditBox::setText(const string &text) {
string output = text; string output = text;
output.replace("\r", ""); output.replace("\r", "");
output.replace("\n", "\r\n"); output.replace("\n", "\r\n");

View File

@@ -1,4 +1,4 @@
static HFONT Font_createFont(const char *name, unsigned size, bool bold, bool italic) { static HFONT Font_createFont(const string &name, unsigned size, bool bold, bool italic) {
return CreateFont( return CreateFont(
-(size * 96.0 / 72.0 + 0.5), -(size * 96.0 / 72.0 + 0.5),
0, 0, 0, bold == false ? FW_NORMAL : FW_BOLD, italic, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bold == false ? FW_NORMAL : FW_BOLD, italic, 0, 0, 0, 0, 0, 0, 0,
@@ -6,7 +6,7 @@ static HFONT Font_createFont(const char *name, unsigned size, bool bold, bool it
); );
} }
bool Font::create(const char *name, unsigned size, Font::Style style) { bool Font::create(const string &name, unsigned size, Font::Style style) {
font->font = Font_createFont( font->font = Font_createFont(
name, size, name, size,
(style & Font::Style::Bold) == Font::Style::Bold, (style & Font::Style::Bold) == Font::Style::Bold,

View File

@@ -1,4 +1,4 @@
void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
widget->window = CreateWindow( widget->window = CreateWindow(
L"phoenix_label", L"", L"phoenix_label", L"",
WS_CHILD | WS_VISIBLE, WS_CHILD | WS_VISIBLE,
@@ -6,12 +6,13 @@ void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsig
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
setText(text); setText(text);
} }
void Label::setText(const char *text) { void Label::setText(const string &text) {
SetWindowText(widget->window, utf16_t(text)); SetWindowText(widget->window, utf16_t(text));
InvalidateRect(widget->window, 0, false);
} }
//all of this for want of a STATIC SS_VCENTER flag ... //all of this for want of a STATIC SS_VCENTER flag ...
@@ -24,28 +25,14 @@ LRESULT CALLBACK Label_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa
Label &label = *label_ptr; Label &label = *label_ptr;
switch(msg) { switch(msg) {
case WM_ERASEBKGND: {
if(window.window->brush == 0) break;
RECT rc;
GetClientRect(window.widget->window, &rc);
PAINTSTRUCT ps;
BeginPaint(window.widget->window, &ps);
FillRect(ps.hdc, &rc, window.window->brush);
EndPaint(window.widget->window, &ps);
return TRUE;
}
case WM_PAINT: { case WM_PAINT: {
PAINTSTRUCT ps; PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
SelectObject(ps.hdc, label.widget->font);
if(window.window->brush) {
SetBkColor(ps.hdc, window.window->brushColor);
} else {
SetBkColor(ps.hdc, GetSysColor(COLOR_3DFACE));
}
RECT rc; RECT rc;
BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc); GetClientRect(hwnd, &rc);
FillRect(ps.hdc, &rc, window.window->brush ? window.window->brush : GetSysColorBrush(COLOR_3DFACE));
SetBkColor(ps.hdc, window.window->brush ? window.window->brushColor : GetSysColor(COLOR_3DFACE));
SelectObject(ps.hdc, label.widget->font);
unsigned length = GetWindowTextLength(hwnd); unsigned length = GetWindowTextLength(hwnd);
wchar_t text[length + 1]; wchar_t text[length + 1];
GetWindowText(hwnd, text, length + 1); GetWindowText(hwnd, text, length + 1);
@@ -57,7 +44,6 @@ LRESULT CALLBACK Label_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa
rc.bottom = rc.top + height; rc.bottom = rc.top + height;
DrawText(ps.hdc, text, -1, &rc, DT_LEFT | DT_END_ELLIPSIS); DrawText(ps.hdc, text, -1, &rc, DT_LEFT | DT_END_ELLIPSIS);
EndPaint(hwnd, &ps); EndPaint(hwnd, &ps);
InvalidateRect(hwnd, 0, false);
} }
} }

View File

@@ -1,4 +1,4 @@
void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
widget->window = CreateWindowEx( widget->window = CreateWindowEx(
WS_EX_CLIENTEDGE, WC_LISTVIEW, L"", WS_EX_CLIENTEDGE, WC_LISTVIEW, L"",
WS_CHILD | WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_VISIBLE |
@@ -7,7 +7,7 @@ void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT); ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT);
lstring list; lstring list;
@@ -34,6 +34,10 @@ void ListBox::setHeaderVisible(bool headerVisible) {
); );
} }
void ListBox::setCheckable(bool checkable) {
ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT | (checkable ? LVS_EX_CHECKBOXES : 0));
}
void ListBox::reset() { void ListBox::reset() {
ListView_DeleteAllItems(widget->window); ListView_DeleteAllItems(widget->window);
} }
@@ -44,7 +48,7 @@ void ListBox::resizeColumnsToContent() {
} }
} }
void ListBox::addItem(const char *text) { void ListBox::addItem(const string &text) {
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
LVITEM item; LVITEM item;
@@ -54,20 +58,28 @@ void ListBox::addItem(const char *text) {
item.iSubItem = 0; item.iSubItem = 0;
utf16_t wtext(list[0]); utf16_t wtext(list[0]);
item.pszText = wtext; item.pszText = wtext;
object->locked = true;
ListView_InsertItem(widget->window, &item); ListView_InsertItem(widget->window, &item);
object->locked = false;
for(unsigned i = 1; i < list.size(); i++) { for(unsigned i = 1; i < list.size(); i++) {
utf16_t wtext(list[i]); utf16_t wtext(list[i]);
ListView_SetItemText(widget->window, row, i, wtext); ListView_SetItemText(widget->window, row, i, wtext);
} }
//workaround: when there is only one column, the horizontal scrollbar will always appear without this
if(listBox->columns == 1) ListView_SetColumnWidth(widget->window, 0, LVSCW_AUTOSIZE_USEHEADER);
} }
void ListBox::setItem(unsigned row, const char *text) { void ListBox::setItem(unsigned row, const string &text) {
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) { for(unsigned i = 0; i < list.size(); i++) {
utf16_t wtext(list[i]); utf16_t wtext(list[i]);
ListView_SetItemText(widget->window, row, i, wtext); ListView_SetItemText(widget->window, row, i, wtext);
} }
//workaround: when there is only one column, the horizontal scrollbar will always appear without this
if(listBox->columns == 1) ListView_SetColumnWidth(widget->window, 0, LVSCW_AUTOSIZE_USEHEADER);
} }
optional<unsigned> ListBox::selection() { optional<unsigned> ListBox::selection() {
@@ -86,6 +98,16 @@ void ListBox::setSelection(unsigned row) {
} }
} }
bool ListBox::checked(unsigned row) {
return ListView_GetCheckState(widget->window, row);
}
void ListBox::setChecked(unsigned row, bool checked) {
object->locked = true;
ListView_SetCheckState(widget->window, row, checked);
object->locked = false;
}
ListBox::ListBox() { ListBox::ListBox() {
listBox = new ListBox::Data; listBox = new ListBox::Data;
listBox->lostFocus = false; listBox->lostFocus = false;

View File

@@ -1,15 +1,15 @@
Action::Action() { Action::Action() {
os.objects.append(this); OS::os->objects.append(this);
action = new Action::Data; action = new Action::Data;
} }
void Menu::create(Window &parent, const char *text) { void Menu::create(Window &parent, const string &text) {
action->parentMenu = parent.window->menu; action->parentMenu = parent.window->menu;
action->menu = CreatePopupMenu(); action->menu = CreatePopupMenu();
AppendMenu(parent.window->menu, MF_STRING | MF_POPUP, (UINT_PTR)action->menu, utf16_t(text)); AppendMenu(parent.window->menu, MF_STRING | MF_POPUP, (UINT_PTR)action->menu, utf16_t(text));
} }
void Menu::create(Menu &parent, const char *text) { void Menu::create(Menu &parent, const string &text) {
action->parentMenu = parent.action->menu; action->parentMenu = parent.action->menu;
action->menu = CreatePopupMenu(); action->menu = CreatePopupMenu();
AppendMenu(parent.action->menu, MF_STRING | MF_POPUP, (UINT_PTR)action->menu, utf16_t(text)); AppendMenu(parent.action->menu, MF_STRING | MF_POPUP, (UINT_PTR)action->menu, utf16_t(text));
@@ -46,7 +46,7 @@ void MenuSeparator::setEnabled(bool enabled) {
EnableMenuItem(action->parent->action->menu, object->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED)); EnableMenuItem(action->parent->action->menu, object->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED));
} }
void MenuItem::create(Menu &parent, const char *text) { void MenuItem::create(Menu &parent, const string &text) {
action->parent = &parent; action->parent = &parent;
AppendMenu(parent.action->menu, MF_STRING, object->id, utf16_t(text)); AppendMenu(parent.action->menu, MF_STRING, object->id, utf16_t(text));
} }
@@ -64,7 +64,7 @@ void MenuItem::setEnabled(bool enabled) {
EnableMenuItem(action->parent->action->menu, object->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED)); EnableMenuItem(action->parent->action->menu, object->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED));
} }
void MenuCheckItem::create(Menu &parent, const char *text) { void MenuCheckItem::create(Menu &parent, const string &text) {
action->parent = &parent; action->parent = &parent;
AppendMenu(parent.action->menu, MF_STRING, object->id, utf16_t(text)); AppendMenu(parent.action->menu, MF_STRING, object->id, utf16_t(text));
} }
@@ -95,7 +95,7 @@ void MenuCheckItem::setChecked(bool checked) {
CheckMenuItem(action->parent->action->menu, object->id, checked ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(action->parent->action->menu, object->id, checked ? MF_CHECKED : MF_UNCHECKED);
} }
void MenuRadioItem::create(Menu &parent, const char *text) { void MenuRadioItem::create(Menu &parent, const string &text) {
action->parent = &parent; action->parent = &parent;
action->radioParent = this; action->radioParent = this;
action->items.append(this); action->items.append(this);
@@ -103,7 +103,7 @@ void MenuRadioItem::create(Menu &parent, const char *text) {
setChecked(); setChecked();
} }
void MenuRadioItem::create(MenuRadioItem &parent, const char *text) { void MenuRadioItem::create(MenuRadioItem &parent, const string &text) {
action->parent = parent.action->parent; action->parent = parent.action->parent;
action->radioParent = parent.action->radioParent; action->radioParent = parent.action->radioParent;
action->radioParent->action->items.append(this); action->radioParent->action->items.append(this);

View File

@@ -8,7 +8,7 @@ static MessageWindow::Response MessageWindow_response(MessageWindow::Buttons but
return MessageWindow::Response::Ok; return MessageWindow::Response::Ok;
} }
MessageWindow::Response MessageWindow::information(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) {
UINT flags = MB_ICONINFORMATION; UINT flags = MB_ICONINFORMATION;
if(buttons == Buttons::Ok) flags |= MB_OK; if(buttons == Buttons::Ok) flags |= MB_OK;
if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL; if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL;
@@ -16,7 +16,7 @@ MessageWindow::Response MessageWindow::information(Window &parent, const char *t
return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.widget->window : 0, utf16_t(text), L"", flags)); return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.widget->window : 0, utf16_t(text), L"", flags));
} }
MessageWindow::Response MessageWindow::question(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) {
UINT flags = MB_ICONQUESTION; UINT flags = MB_ICONQUESTION;
if(buttons == Buttons::Ok) flags |= MB_OK; if(buttons == Buttons::Ok) flags |= MB_OK;
if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL; if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL;
@@ -24,7 +24,7 @@ MessageWindow::Response MessageWindow::question(Window &parent, const char *text
return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.widget->window : 0, utf16_t(text), L"", flags)); return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.widget->window : 0, utf16_t(text), L"", flags));
} }
MessageWindow::Response MessageWindow::warning(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) {
UINT flags = MB_ICONWARNING; UINT flags = MB_ICONWARNING;
if(buttons == Buttons::Ok) flags |= MB_OK; if(buttons == Buttons::Ok) flags |= MB_OK;
if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL; if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL;
@@ -32,7 +32,7 @@ MessageWindow::Response MessageWindow::warning(Window &parent, const char *text,
return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.widget->window : 0, utf16_t(text), L"", flags)); return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.widget->window : 0, utf16_t(text), L"", flags));
} }
MessageWindow::Response MessageWindow::critical(Window &parent, const char *text, MessageWindow::Buttons buttons) { MessageWindow::Response MessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) {
UINT flags = MB_ICONERROR; UINT flags = MB_ICONERROR;
if(buttons == Buttons::Ok) flags |= MB_OK; if(buttons == Buttons::Ok) flags |= MB_OK;
if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL; if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL;

View File

@@ -70,6 +70,7 @@ struct VerticalSlider::Data {
}; };
struct OS::Data { struct OS::Data {
nall::array<Object*> objects;
HFONT proportionalFont; HFONT proportionalFont;
HFONT monospaceFont; HFONT monospaceFont;
}; };
@@ -78,6 +79,7 @@ void Object::unused() {
} }
Object::Object() { Object::Object() {
OS::initialize();
static unsigned guid = 100; static unsigned guid = 100;
object = new Object::Data; object = new Object::Data;
object->id = guid++; object->id = guid++;

View File

@@ -9,10 +9,10 @@ void ProgressBar::create(Window &parent, unsigned x, unsigned y, unsigned width,
SendMessage(widget->window, PBM_SETSTEP, MAKEWPARAM(1, 0), 0); SendMessage(widget->window, PBM_SETSTEP, MAKEWPARAM(1, 0), 0);
} }
unsigned ProgressBar::progress() { unsigned ProgressBar::position() {
return SendMessage(widget->window, PBM_GETPOS, 0, 0); return SendMessage(widget->window, PBM_GETPOS, 0, 0);
} }
void ProgressBar::setProgress(unsigned progress) { void ProgressBar::setPosition(unsigned position) {
SendMessage(widget->window, PBM_SETPOS, (WPARAM)progress, 0); SendMessage(widget->window, PBM_SETPOS, (WPARAM)position, 0);
} }

View File

@@ -1,4 +1,4 @@
void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
radioBox->parentWindow = &parent; radioBox->parentWindow = &parent;
radioBox->parent = this; radioBox->parent = this;
radioBox->parent->radioBox->items.append(this); radioBox->parent->radioBox->items.append(this);
@@ -9,11 +9,11 @@ void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, un
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
setChecked(); setChecked();
} }
void RadioBox::create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void RadioBox::create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
radioBox->parentWindow = parent.radioBox->parentWindow; radioBox->parentWindow = parent.radioBox->parentWindow;
radioBox->parent = parent.radioBox->parent; radioBox->parent = parent.radioBox->parent;
radioBox->parent->radioBox->items.append(this); radioBox->parent->radioBox->items.append(this);
@@ -24,7 +24,7 @@ void RadioBox::create(RadioBox &parent, unsigned x, unsigned y, unsigned width,
GetParent(radioBox->parent->widget->window), (HMENU)object->id, GetModuleHandle(0), 0 GetParent(radioBox->parent->widget->window), (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(radioBox->parentWindow->window->defaultFont ? radioBox->parentWindow->window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(radioBox->parentWindow->window->defaultFont ? radioBox->parentWindow->window->defaultFont : OS::os->proportionalFont), 0);
} }
bool RadioBox::checked() { bool RadioBox::checked() {

View File

@@ -1,4 +1,4 @@
void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
widget->window = CreateWindowEx( widget->window = CreateWindowEx(
WS_EX_CLIENTEDGE, L"EDIT", utf16_t(text), WS_EX_CLIENTEDGE, L"EDIT", utf16_t(text),
WS_CHILD | WS_TABSTOP | WS_VISIBLE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, WS_CHILD | WS_TABSTOP | WS_VISIBLE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
@@ -6,7 +6,7 @@ void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
} }
string TextBox::text() { string TextBox::text() {
@@ -17,7 +17,7 @@ string TextBox::text() {
return utf8_t(text); return utf8_t(text);
} }
void TextBox::setText(const char *text) { void TextBox::setText(const string &text) {
object->locked = true; object->locked = true;
SetWindowText(widget->window, utf16_t(text)); SetWindowText(widget->window, utf16_t(text));
object->locked = false; object->locked = false;

View File

@@ -1,6 +1,6 @@
void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) { void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) {
widget->window = CreateWindow( widget->window = CreateWindow(
L"phoenix_window", L"", L"phoenix_viewport", L"",
WS_CHILD | WS_VISIBLE | WS_DISABLED, WS_CHILD | WS_VISIBLE | WS_DISABLED,
x, y, width, height, x, y, width, height,
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
@@ -11,3 +11,7 @@ void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, un
uintptr_t Viewport::handle() { uintptr_t Viewport::handle() {
return (uintptr_t)widget->window; return (uintptr_t)widget->window;
} }
static LRESULT CALLBACK Viewport_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
return DefWindowProc(hwnd, msg, wparam, lparam);
}

View File

@@ -28,9 +28,13 @@ void Widget::setFocused() {
SetFocus(widget->window); SetFocus(widget->window);
} }
void Widget::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
SetWindowPos(widget->window, NULL, x, y, width, height, SWP_NOZORDER);
}
Widget::Widget() { Widget::Widget() {
os.objects.append(this); OS::os->objects.append(this);
widget = new Widget::Data; widget = new Widget::Data;
widget->window = 0; widget->window = 0;
widget->font = os.os->proportionalFont; widget->font = OS::os->proportionalFont;
} }

View File

@@ -1,4 +1,4 @@
void Window::create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void Window::create(unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
widget->window = CreateWindowEx( widget->window = CreateWindowEx(
0, L"phoenix_window", utf16_t(text), 0, L"phoenix_window", utf16_t(text),
WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
@@ -26,6 +26,18 @@ void Window::setFont(Font &font) {
SendMessage(window->status, WM_SETFONT, (WPARAM)font.font->font, 0); SendMessage(window->status, WM_SETFONT, (WPARAM)font.font->font, 0);
} }
Geometry Window::geometry() {
RECT position, size;
GetWindowRect(widget->window, &position);
GetClientRect(widget->window, &size);
if(GetWindowLongPtr(window->status, GWL_STYLE) & WS_VISIBLE) {
RECT status;
GetClientRect(window->status, &status);
size.bottom -= status.bottom - status.top;
}
return Geometry(position.left, position.top, size.right, size.bottom);
}
void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) { void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
bool isVisible = visible(); bool isVisible = visible();
if(isVisible) setVisible(false); if(isVisible) setVisible(false);
@@ -40,11 +52,11 @@ void Window::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
window->brush = CreateSolidBrush(window->brushColor); window->brush = CreateSolidBrush(window->brushColor);
} }
void Window::setTitle(const char *text) { void Window::setTitle(const string &text) {
SetWindowText(widget->window, utf16_t(text)); SetWindowText(widget->window, utf16_t(text));
} }
void Window::setStatusText(const char *text) { void Window::setStatusText(const string &text) {
SendMessage(window->status, SB_SETTEXT, 0, (LPARAM)(wchar_t*)utf16_t(text)); SendMessage(window->status, SB_SETTEXT, 0, (LPARAM)(wchar_t*)utf16_t(text));
} }

View File

@@ -29,14 +29,72 @@ namespace phoenix {
#include "viewport.cpp" #include "viewport.cpp"
#include "messagewindow.cpp" #include "messagewindow.cpp"
OS &os = OS::handle(); OS::Data *OS::os = 0;
Window Window::None; Window Window::None;
static void OS_keyboardProc(HWND, UINT, WPARAM, LPARAM); static void OS_keyboardProc(HWND, UINT, WPARAM, LPARAM);
static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
OS& OS::handle() { void OS::initialize() {
static OS os; static bool initialized = false;
return os; if(initialized == true) return;
initialized = true;
InitCommonControls();
CoInitialize(0);
os = new OS::Data;
os->proportionalFont = Font_createFont("Tahoma", 8, false, false);
os->monospaceFont = Font_createFont("Courier New", 8, false, false);
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = OS_windowProc;
wc.lpszClassName = L"phoenix_window";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Canvas_windowProc;
wc.lpszClassName = L"phoenix_canvas";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Label_windowProc;
wc.lpszClassName = L"phoenix_label";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Viewport_windowProc;
wc.lpszClassName = L"phoenix_viewport";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
} }
bool OS::pending() { bool OS::pending() {
@@ -84,7 +142,7 @@ unsigned OS::desktopHeight() {
return GetSystemMetrics(SM_CYSCREEN); return GetSystemMetrics(SM_CYSCREEN);
} }
string OS::folderSelect(Window &parent, const char *path) { string OS::folderSelect(Window &parent, const string &path) {
wchar_t wfilename[PATH_MAX + 1] = L""; wchar_t wfilename[PATH_MAX + 1] = L"";
BROWSEINFO bi; BROWSEINFO bi;
bi.hwndOwner = &parent != &Window::None ? parent.widget->window : 0; bi.hwndOwner = &parent != &Window::None ? parent.widget->window : 0;
@@ -108,10 +166,13 @@ string OS::folderSelect(Window &parent, const char *path) {
} }
} }
if(result == false) return ""; if(result == false) return "";
return utf8_t(wfilename); string name = utf8_t(wfilename);
name.transform("\\", "/");
if(name.endswith("/") == false) name.append("/");
return name;
} }
string OS::fileOpen(Window &parent, const char *filter, const char *path) { string OS::fileOpen(Window &parent, const string &filter, const string &path) {
string dir = path; string dir = path;
dir.replace("/", "\\"); dir.replace("/", "\\");
@@ -154,10 +215,12 @@ string OS::fileOpen(Window &parent, const char *filter, const char *path) {
bool result = GetOpenFileName(&ofn); bool result = GetOpenFileName(&ofn);
if(result == false) return ""; if(result == false) return "";
return utf8_t(wfilename); string name = utf8_t(wfilename);
name.transform("\\", "/");
return name;
} }
string OS::fileSave(Window &parent, const char *filter, const char *path) { string OS::fileSave(Window &parent, const string &filter, const string &path) {
string dir = path; string dir = path;
dir.replace("/", "\\"); dir.replace("/", "\\");
@@ -200,7 +263,9 @@ string OS::fileSave(Window &parent, const char *filter, const char *path) {
bool result = GetSaveFileName(&ofn); bool result = GetSaveFileName(&ofn);
if(result == false) return ""; if(result == false) return "";
return utf8_t(wfilename); string name = utf8_t(wfilename);
name.transform("\\", "/");
return name;
} }
static void OS_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { static void OS_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
@@ -211,11 +276,18 @@ static void OS_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
info.cbSize = sizeof(GUITHREADINFO); info.cbSize = sizeof(GUITHREADINFO);
GetGUIThreadInfo(GetCurrentThreadId(), &info); GetGUIThreadInfo(GetCurrentThreadId(), &info);
Object *object_ptr = (Object*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA); Object *object_ptr = (Object*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA);
if(object_ptr && dynamic_cast<ListBox*>(object_ptr)) { if(object_ptr) {
if(dynamic_cast<ListBox*>(object_ptr)) {
ListBox &listBox = (ListBox&)*object_ptr; ListBox &listBox = (ListBox&)*object_ptr;
if(wparam == VK_RETURN) { if(wparam == VK_RETURN) {
if(listBox.onActivate) listBox.onActivate(); if(listBox.onActivate) listBox.onActivate();
} }
} else if(dynamic_cast<TextBox*>(object_ptr)) {
TextBox &textBox = (TextBox&)*object_ptr;
if(wparam == VK_RETURN) {
if(textBox.onActivate) textBox.onActivate();
}
}
} }
} }
} }
@@ -261,7 +333,7 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
unsigned id = LOWORD(wparam); unsigned id = LOWORD(wparam);
HWND control = GetDlgItem(window.widget->window, id); HWND control = GetDlgItem(window.widget->window, id);
if(control == 0) { if(control == 0) {
Object *object_ptr = (Object*)os.findObject(id); Object *object_ptr = (Object*)OS::findObject(id);
if(object_ptr) { if(object_ptr) {
if(dynamic_cast<MenuItem*>(object_ptr)) { if(dynamic_cast<MenuItem*>(object_ptr)) {
MenuItem &menuItem = (MenuItem&)*object_ptr; MenuItem &menuItem = (MenuItem&)*object_ptr;
@@ -327,8 +399,12 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
ListBox &listBox = (ListBox&)*object_ptr; ListBox &listBox = (ListBox&)*object_ptr;
LPNMHDR nmhdr = (LPNMHDR)lparam; LPNMHDR nmhdr = (LPNMHDR)lparam;
LPNMLISTVIEW nmlistview = (LPNMLISTVIEW)lparam; LPNMLISTVIEW nmlistview = (LPNMLISTVIEW)lparam;
if(nmhdr->code == LVN_ITEMCHANGED && (nmlistview->uChanged & LVIF_STATE)) { if(nmhdr->code == LVN_ITEMCHANGED && (nmlistview->uChanged & LVIF_STATE)) {
if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) { unsigned imagemask = ((nmlistview->uNewState & LVIS_STATEIMAGEMASK) >> 12) - 1;
if(imagemask == 0 || imagemask == 1) {
if(listBox.object->locked == false && listBox.onTick) listBox.onTick(nmlistview->iItem);
} else if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) {
listBox.listBox->lostFocus = true; listBox.listBox->lostFocus = true;
} else { } else {
if(!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED)) { if(!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED)) {
@@ -385,54 +461,8 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
} }
Object* OS::findObject(unsigned id) { Object* OS::findObject(unsigned id) {
foreach(object, objects) { if(object->object->id == id) return object; } foreach(object, os->objects) { if(object->object->id == id) return object; }
return 0; return 0;
} }
OS::OS() {
InitCommonControls();
CoInitialize(0);
os = new OS::Data;
os->proportionalFont = Font_createFont("Tahoma", 8, false, false);
os->monospaceFont = Font_createFont("Courier New", 8, false, false);
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = OS_windowProc;
wc.lpszClassName = L"phoenix_window";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Canvas_windowProc;
wc.lpszClassName = L"phoenix_canvas";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Label_windowProc;
wc.lpszClassName = L"phoenix_label";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
}
} }

View File

@@ -4,6 +4,8 @@ struct Window;
struct Object { struct Object {
Object(); Object();
Object& operator=(const Object&) = delete;
Object(const Object&) = delete;
//private: //private:
struct Data; struct Data;
Data *object; Data *object;
@@ -11,13 +13,20 @@ private:
virtual void unused(); virtual void unused();
}; };
struct Geometry {
unsigned x, y;
unsigned width, height;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(unsigned x, unsigned y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
};
struct Font : Object { struct Font : Object {
enum class Style : unsigned { enum class Style : unsigned {
None = 0, None = 0,
Bold = 1, Bold = 1,
Italic = 2, Italic = 2,
}; };
bool create(const char *name, unsigned size, Font::Style style = Style::None); bool create(const nall::string &name, unsigned size, Font::Style style = Style::None);
Font(); Font();
~Font(); ~Font();
//private: //private:
@@ -38,8 +47,8 @@ struct Action : Object {
}; };
struct Menu : Action { struct Menu : Action {
void create(Window &parent, const char *text); void create(Window &parent, const nall::string &text);
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
bool enabled(); bool enabled();
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
}; };
@@ -52,14 +61,14 @@ struct MenuSeparator : Action {
struct MenuItem : Action { struct MenuItem : Action {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
bool enabled(); bool enabled();
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
}; };
struct MenuCheckItem : Action { struct MenuCheckItem : Action {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
bool enabled(); bool enabled();
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
bool checked(); bool checked();
@@ -68,8 +77,8 @@ struct MenuCheckItem : Action {
struct MenuRadioItem : Action { struct MenuRadioItem : Action {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Menu &parent, const char *text); void create(Menu &parent, const nall::string &text);
void create(MenuRadioItem &parent, const char *text); void create(MenuRadioItem &parent, const nall::string &text);
bool enabled(); bool enabled();
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
bool checked(); bool checked();
@@ -84,6 +93,7 @@ struct Widget : Object {
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
bool focused(); bool focused();
void setFocused(); void setFocused();
virtual void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
Widget(); Widget();
//private: //private:
struct Data; struct Data;
@@ -91,28 +101,28 @@ struct Widget : Object {
}; };
struct Window : Widget { struct Window : Widget {
static Window None;
nall::function<bool ()> onClose; nall::function<bool ()> onClose;
void create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setDefaultFont(Font &font); void setDefaultFont(Font &font);
void setFont(Font &font); void setFont(Font &font);
Geometry geometry();
void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height); void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue); void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
void setTitle(const char *text); void setTitle(const nall::string &text);
void setStatusText(const char *text); void setStatusText(const nall::string &text);
void setMenuVisible(bool visible = true); void setMenuVisible(bool visible = true);
void setStatusVisible(bool visible = true); void setStatusVisible(bool visible = true);
Window(); Window();
//private: //private:
struct Data; struct Data;
Data *window; Data *window;
//private: static Window None;
void resize(unsigned width, unsigned height); void resize(unsigned width, unsigned height);
}; };
struct Button : Widget { struct Button : Widget {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
}; };
struct Canvas : Widget { struct Canvas : Widget {
@@ -128,16 +138,16 @@ struct Canvas : Widget {
struct CheckBox : Widget { struct CheckBox : Widget {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
bool checked(); bool checked();
void setChecked(bool checked = true); void setChecked(bool checked = true);
}; };
struct ComboBox : Widget { struct ComboBox : Widget {
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void reset(); void reset();
void addItem(const char *text); void addItem(const nall::string &text);
unsigned selection(); unsigned selection();
void setSelection(unsigned item); void setSelection(unsigned item);
ComboBox(); ComboBox();
@@ -148,9 +158,9 @@ struct ComboBox : Widget {
struct EditBox : Widget { struct EditBox : Widget {
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
nall::string getText(); nall::string getText();
void setText(const char *text); void setText(const nall::string &text);
void setEditable(bool editable = true); void setEditable(bool editable = true);
void setWordWrap(bool wordWrap = true); void setWordWrap(bool wordWrap = true);
EditBox(); EditBox();
@@ -171,19 +181,23 @@ struct HorizontalSlider : Widget {
}; };
struct Label : Widget { struct Label : Widget {
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setText(const char *text); void setText(const nall::string &text);
}; };
struct ListBox : Widget { struct ListBox : Widget {
nall::function<void ()> onActivate; nall::function<void ()> onActivate;
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); nall::function<void (unsigned)> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setHeaderVisible(bool headerVisible = true); void setHeaderVisible(bool headerVisible = true);
void setCheckable(bool checkable = true);
void reset(); void reset();
void resizeColumnsToContent(); void resizeColumnsToContent();
void addItem(const char *text); void addItem(const nall::string &text);
void setItem(unsigned row, const char *text); void setItem(unsigned row, const nall::string &text);
bool checked(unsigned row);
void setChecked(unsigned row, bool checked = true);
nall::optional<unsigned> selection(); nall::optional<unsigned> selection();
void setSelection(unsigned row); void setSelection(unsigned row);
ListBox(); ListBox();
@@ -194,14 +208,14 @@ struct ListBox : Widget {
struct ProgressBar : Widget { struct ProgressBar : Widget {
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height);
unsigned progress(); unsigned position();
void setProgress(unsigned progress); void setPosition(unsigned position);
}; };
struct RadioBox : Widget { struct RadioBox : Widget {
nall::function<void ()> onTick; nall::function<void ()> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(RadioBox &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
bool checked(); bool checked();
void setChecked(); void setChecked();
RadioBox(); RadioBox();
@@ -211,10 +225,11 @@ struct RadioBox : Widget {
}; };
struct TextBox : Widget { struct TextBox : Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange; nall::function<void ()> onChange;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
nall::string text(); nall::string text();
void setText(const char *text); void setText(const nall::string &text);
void setEditable(bool editable = true); void setEditable(bool editable = true);
}; };
@@ -246,33 +261,28 @@ struct MessageWindow : Object {
Yes, Yes,
No, No,
}; };
static Response information(Window &parent, const char *text, Buttons = Buttons::Ok); static Response information(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response question(Window &parent, const char *text, Buttons = Buttons::YesNo); static Response question(Window &parent, const nall::string &text, Buttons = Buttons::YesNo);
static Response warning(Window &parent, const char *text, Buttons = Buttons::Ok); static Response warning(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response critical(Window &parent, const char *text, Buttons = Buttons::Ok); static Response critical(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
}; };
struct OS : Object { struct OS : Object {
bool pending(); static bool pending();
void run(); static void run();
void main(); static void main();
void quit(); static void quit();
unsigned desktopWidth(); static unsigned desktopWidth();
unsigned desktopHeight(); static unsigned desktopHeight();
nall::string folderSelect(Window &parent, const char *path = ""); static nall::string folderSelect(Window &parent, const nall::string &path = "");
nall::string fileOpen(Window &parent, const char *filter, const char *path = ""); static nall::string fileOpen(Window &parent, const nall::string &filter, const nall::string &path = "");
nall::string fileSave(Window &parent, const char *filter, const char *path = ""); static nall::string fileSave(Window &parent, const nall::string &filter, const nall::string &path = "");
//private: //private:
static OS& handle(); static void initialize();
struct Data; struct Data;
Data *os; static Data *os;
Object* findObject(unsigned id); static Object* findObject(unsigned id);
nall::array<Object*> objects;
private:
OS();
friend class Object; friend class Object;
}; };
extern OS &os;
}; };

View File

@@ -277,8 +277,8 @@ public:
//this is used to sort device IDs //this is used to sort device IDs
struct DevicePool { struct DevicePool {
HANDLE handle; HANDLE handle;
char name[4096]; wchar_t name[4096];
bool operator<(const DevicePool &pool) const { return strcmp(name, pool.name) < 0; } bool operator<(const DevicePool &pool) const { return wcscmp(name, pool.name) < 0; }
}; };
int main() { int main() {
@@ -342,8 +342,12 @@ public:
//per MSDN: XInput devices have "IG_" in their device strings, //per MSDN: XInput devices have "IG_" in their device strings,
//which is how they should be identified. //which is how they should be identified.
const char *p = strstr(pool[i].name, "IG_"); string p = utf8_t(pool[i].name);
lgamepad[n].isXInputDevice = (bool)p; if(auto position = strpos(p, "IG_")) {
lgamepad[n].isXInputDevice = true;
} else {
lgamepad[n].isXInputDevice = false;
}
} }
} }
} }
@@ -693,7 +697,9 @@ public:
//========= //=========
for(unsigned i = 0; i < min(rawinput.lkeyboard.size(), (unsigned)Keyboard::Count); i++) { for(unsigned i = 0; i < min(rawinput.lkeyboard.size(), (unsigned)Keyboard::Count); i++) {
for(unsigned n = 0; n < nall::Keyboard::Size; n++) { for(unsigned n = 0; n < nall::Keyboard::Size; n++) {
table[keyboard(i).key(n)] = rawinput.lkeyboard[i].state[n]; //using keyboard(0)|= instead of keyboard(i)= merges all keyboards to KB0
//this is done to favor ease of mapping over flexibility (eg share laptop+USB keyboard mapping)
table[keyboard(0).key(n)] |= rawinput.lkeyboard[i].state[n];
} }
} }
@@ -723,15 +729,17 @@ public:
for(unsigned i = 0; i < xinput.lgamepad.size(); i++) { for(unsigned i = 0; i < xinput.lgamepad.size(); i++) {
if(joy >= Joypad::Count) break; if(joy >= Joypad::Count) break;
table[joypad(i).hat(0)] = xinput.lgamepad[i].hat; table[joypad(joy).hat(0)] = xinput.lgamepad[i].hat;
for(unsigned axis = 0; axis < min(6U, (unsigned)Joypad::Axes); axis++) { for(unsigned axis = 0; axis < min(6U, (unsigned)Joypad::Axes); axis++) {
table[joypad(i).axis(axis)] = xinput.lgamepad[i].axis[axis]; table[joypad(joy).axis(axis)] = xinput.lgamepad[i].axis[axis];
} }
for(unsigned button = 0; button < min(10U, (unsigned)Joypad::Buttons); button++) { for(unsigned button = 0; button < min(10U, (unsigned)Joypad::Buttons); button++) {
table[joypad(i).button(button)] = xinput.lgamepad[i].button[button]; table[joypad(joy).button(button)] = xinput.lgamepad[i].button[button];
} }
joy++;
} }
//======================= //=======================
@@ -742,16 +750,18 @@ public:
if(joy >= Joypad::Count) break; if(joy >= Joypad::Count) break;
for(unsigned hat = 0; hat < min(4U, (unsigned)Joypad::Hats); hat++) { for(unsigned hat = 0; hat < min(4U, (unsigned)Joypad::Hats); hat++) {
table[joypad(i).hat(hat)] = dinput.lgamepad[i].hat[hat]; table[joypad(joy).hat(hat)] = dinput.lgamepad[i].hat[hat];
} }
for(unsigned axis = 0; axis < min(6U, (unsigned)Joypad::Axes); axis++) { for(unsigned axis = 0; axis < min(6U, (unsigned)Joypad::Axes); axis++) {
table[joypad(i).axis(axis)] = dinput.lgamepad[i].axis[axis]; table[joypad(joy).axis(axis)] = dinput.lgamepad[i].axis[axis];
} }
for(unsigned button = 0; button < min(128U, (unsigned)Joypad::Buttons); button++) { for(unsigned button = 0; button < min(128U, (unsigned)Joypad::Buttons); button++) {
table[joypad(i).button(button)] = dinput.lgamepad[i].button[button]; table[joypad(joy).button(button)] = dinput.lgamepad[i].button[button];
} }
joy++;
} }
return true; return true;

View File

@@ -14,6 +14,7 @@ InputInterface input;
const char *Video::Handle = "Handle"; const char *Video::Handle = "Handle";
const char *Video::Synchronize = "Synchronize"; const char *Video::Synchronize = "Synchronize";
const char *Video::Filter = "Filter"; const char *Video::Filter = "Filter";
const char *Video::Shader = "Shader";
const char *Video::FragmentShader = "FragmentShader"; const char *Video::FragmentShader = "FragmentShader";
const char *Video::VertexShader = "VertexShader"; const char *Video::VertexShader = "VertexShader";

View File

@@ -3,6 +3,7 @@ public:
static const char *Handle; static const char *Handle;
static const char *Synchronize; static const char *Synchronize;
static const char *Filter; static const char *Filter;
static const char *Shader;
static const char *FragmentShader; static const char *FragmentShader;
static const char *VertexShader; static const char *VertexShader;

View File

@@ -24,7 +24,7 @@ public:
LPDIRECT3DTEXTURE9 texture; LPDIRECT3DTEXTURE9 texture;
LPDIRECT3DSURFACE9 surface; LPDIRECT3DSURFACE9 surface;
LPD3DXEFFECT effect; LPD3DXEFFECT effect;
string shaderSource; string shader_source_xml;
bool lost; bool lost;
unsigned iwidth, iheight; unsigned iwidth, iheight;
@@ -64,7 +64,7 @@ public:
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true; if(name == Video::Synchronize) return true;
if(name == Video::Filter) return true; if(name == Video::Filter) return true;
if(name == Video::FragmentShader) return true; if(name == Video::Shader) return true;
return false; return false;
} }
@@ -92,8 +92,8 @@ public:
return true; return true;
} }
if(name == Video::FragmentShader) { if(name == Video::Shader) {
set_fragment_shader(any_cast<const char*>(value)); set_shader(any_cast<const char*>(value));
return true; return true;
} }
@@ -268,7 +268,7 @@ public:
//failure to do so causes scaling issues on some video drivers. //failure to do so causes scaling issues on some video drivers.
if(state.width != rd.right || state.height != rd.bottom) { if(state.width != rd.right || state.height != rd.bottom) {
init(); init();
set_fragment_shader(shaderSource); set_shader(shader_source_xml);
return; return;
} }
@@ -327,7 +327,7 @@ public:
if(device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) lost = true; if(device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) lost = true;
} }
void set_fragment_shader(const char *source) { void set_shader(const char *source) {
if(!caps.shader) return; if(!caps.shader) return;
if(effect) { if(effect) {
@@ -336,11 +336,27 @@ public:
} }
if(!source || !*source) { if(!source || !*source) {
shaderSource = ""; shader_source_xml = "";
return; return;
} }
shader_source_xml = source;
shaderSource = source; bool is_hlsl = false;
string shader_source;
xml_element document = xml_parse(shader_source_xml);
foreach(head, document.element) {
if(head.name == "shader") {
foreach(attribute, head.attribute) {
if(attribute.name == "language" && attribute.content == "HLSL") is_hlsl = true;
}
foreach(element, head.element) {
if(element.name == "source") {
if(is_hlsl) shader_source = element.parse();
}
}
}
}
if(shader_source == "") return;
HMODULE d3dx; HMODULE d3dx;
for(unsigned i = 0; i < 256; i++) { for(unsigned i = 0; i < 256; i++) {
@@ -349,14 +365,14 @@ public:
d3dx = LoadLibraryW(utf16_t(t)); d3dx = LoadLibraryW(utf16_t(t));
if(d3dx) break; if(d3dx) break;
} }
if(!d3dx) d3dx = LoadLibrary(L"d3dx9.dll"); if(!d3dx) d3dx = LoadLibraryW(L"d3dx9.dll");
if(!d3dx) return; if(!d3dx) return;
EffectProc effectProc = (EffectProc)GetProcAddress(d3dx, "D3DXCreateEffect"); EffectProc effectProc = (EffectProc)GetProcAddress(d3dx, "D3DXCreateEffect");
TextureProc textureProc = (TextureProc)GetProcAddress(d3dx, "D3DXCreateTextureFromFileA"); TextureProc textureProc = (TextureProc)GetProcAddress(d3dx, "D3DXCreateTextureFromFileA");
LPD3DXBUFFER pBufferErrors = NULL; LPD3DXBUFFER pBufferErrors = NULL;
effectProc(device, utf16_t(shaderSource), lstrlen(utf16_t(source)), NULL, NULL, 0, NULL, &effect, &pBufferErrors); effectProc(device, shader_source, lstrlenA(shader_source), NULL, NULL, 0, NULL, &effect, &pBufferErrors);
D3DXHANDLE hTech; D3DXHANDLE hTech;
effect->FindNextValidTechnique(NULL, &hTech); effect->FindNextValidTechnique(NULL, &hTech);

View File

@@ -2,7 +2,7 @@
video.glx video.glx
author: byuu author: byuu
license: public domain license: public domain
last updated: 2010-01-05 last updated: 2010-09-28
Design notes: Design notes:
SGI's GLX is the X11/Xlib interface to OpenGL. SGI's GLX is the X11/Xlib interface to OpenGL.
@@ -62,6 +62,7 @@ public:
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true; if(name == Video::Synchronize) return true;
if(name == Video::Filter) return true; if(name == Video::Filter) return true;
if(name == Video::Shader) return true;
if(name == Video::FragmentShader) return true; if(name == Video::FragmentShader) return true;
if(name == Video::VertexShader) return true; if(name == Video::VertexShader) return true;
return false; return false;
@@ -93,6 +94,11 @@ public:
return true; return true;
} }
if(name == Video::Shader) {
OpenGL::set_shader(any_cast<const char*>(value));
return true;
}
if(name == Video::FragmentShader) { if(name == Video::FragmentShader) {
OpenGL::set_fragment_shader(any_cast<const char*>(value)); OpenGL::set_fragment_shader(any_cast<const char*>(value));
return true; return true;

View File

@@ -122,7 +122,7 @@ public:
} }
} }
void set_fragment_shader(const char *source) { void set_shader(const char *source) {
if(!shader_support) return; if(!shader_support) return;
if(fragmentshader) { if(fragmentshader) {
@@ -131,19 +131,6 @@ public:
fragmentshader = 0; fragmentshader = 0;
} }
if(source) {
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentshader, 1, &source, 0);
glCompileShader(fragmentshader);
glAttachShader(glprogram, fragmentshader);
}
glLinkProgram(glprogram);
}
void set_vertex_shader(const char *source) {
if(!shader_support) return;
if(vertexshader) { if(vertexshader) {
glDetachShader(glprogram, vertexshader); glDetachShader(glprogram, vertexshader);
glDeleteShader(vertexshader); glDeleteShader(vertexshader);
@@ -151,15 +138,49 @@ public:
} }
if(source) { if(source) {
bool is_glsl = false;
string fragment_source;
string vertex_source;
xml_element document = xml_parse(source);
foreach(head, document.element) {
if(head.name == "shader") {
foreach(attribute, head.attribute) {
if(attribute.name == "language" && attribute.content == "GLSL") is_glsl = true;
}
foreach(element, head.element) {
if(element.name == "fragment") {
fragment_source = element.parse();
} else if(element.name == "vertex") {
vertex_source = element.parse();
}
}
}
}
if(is_glsl) {
if(fragment_source != "") set_fragment_shader(fragment_source);
if(vertex_source != "") set_vertex_shader(vertex_source);
}
}
glLinkProgram(glprogram);
}
void set_fragment_shader(const char *source) {
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentshader, 1, &source, 0);
glCompileShader(fragmentshader);
glAttachShader(glprogram, fragmentshader);
}
void set_vertex_shader(const char *source) {
vertexshader = glCreateShader(GL_VERTEX_SHADER); vertexshader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexshader, 1, &source, 0); glShaderSource(vertexshader, 1, &source, 0);
glCompileShader(vertexshader); glCompileShader(vertexshader);
glAttachShader(glprogram, vertexshader); glAttachShader(glprogram, vertexshader);
} }
glLinkProgram(glprogram);
}
void init() { void init() {
//disable unused features //disable unused features
glDisable(GL_ALPHA_TEST); glDisable(GL_ALPHA_TEST);

View File

@@ -29,8 +29,7 @@ public:
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true; if(name == Video::Synchronize) return true;
if(name == Video::Filter) return true; if(name == Video::Filter) return true;
if(name == Video::FragmentShader) return true; if(name == Video::Shader) return true;
if(name == Video::VertexShader) return true;
return false; return false;
} }
@@ -59,13 +58,8 @@ public:
return true; return true;
} }
if(name == Video::FragmentShader) { if(name == Video::Shader) {
OpenGL::set_fragment_shader(any_cast<const char*>(value)); OpenGL::set_shader(any_cast<const char*>(value));
return true;
}
if(name == Video::VertexShader) {
OpenGL::set_vertex_shader(any_cast<const char*>(value));
return true; return true;
} }

View File

@@ -5,7 +5,7 @@ uint8 CPU::pio() {
} }
bool CPU::joylatch() { bool CPU::joylatch() {
return 0; return status.joypad_strobe_latch;
} }
bool CPU::interrupt_pending() { bool CPU::interrupt_pending() {

View File

@@ -75,7 +75,7 @@ void PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) {
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1]; palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
} break; } break;
case 2: { //palette color 0 outside of screen area case 2: { //palette color 0 outside of screen area
if(px < 0 || px > 1023 || py < 0 || py > 1023) { if((px | py) & ~1023) {
palette = 0; palette = 0;
} else { } else {
px &= 1023; px &= 1023;
@@ -87,7 +87,7 @@ void PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) {
} }
} break; } break;
case 3: { //character 0 repetition outside of screen area case 3: { //character 0 repetition outside of screen area
if(px < 0 || px > 1023 || py < 0 || py > 1023) { if((px | py) & ~1023) {
tile = 0; tile = 0;
} else { } else {
px &= 1023; px &= 1023;

View File

@@ -43,10 +43,10 @@ void PPU::Background::offset_per_tile(unsigned x, unsigned y, unsigned &hoffset,
void PPU::Background::scanline() { void PPU::Background::scanline() {
if(self.vcounter() == 1) { if(self.vcounter() == 1) {
mosaic_vcounter = regs.mosaic + 1; mosaic_vcounter = regs.mosaic + 1;
y = 1; mosaic_voffset = 1;
} else if(--mosaic_vcounter == 0) { } else if(--mosaic_vcounter == 0) {
mosaic_vcounter = regs.mosaic + 1; mosaic_vcounter = regs.mosaic + 1;
y += regs.mosaic + 1; mosaic_voffset += regs.mosaic + 1;
} }
if(self.regs.display_disable) return; if(self.regs.display_disable) return;
@@ -93,7 +93,7 @@ void PPU::Background::render() {
hscroll = regs.hoffset; hscroll = regs.hoffset;
vscroll = regs.voffset; vscroll = regs.voffset;
unsigned y = Background::y; unsigned y = (regs.mosaic == 0 ? self.vcounter() : mosaic_voffset);
if(hires) { if(hires) {
hscroll <<= 1; hscroll <<= 1;
if(self.regs.interlace) y = (y << 1) + self.field(); if(self.regs.interlace) y = (y << 1) + self.field();

View File

@@ -31,7 +31,6 @@ class Background {
const unsigned id; const unsigned id;
unsigned opt_valid_bit; unsigned opt_valid_bit;
unsigned y;
bool hires; bool hires;
signed width; signed width;
@@ -48,6 +47,7 @@ class Background {
unsigned vscroll; unsigned vscroll;
unsigned mosaic_vcounter; unsigned mosaic_vcounter;
unsigned mosaic_voffset;
LayerWindow window; LayerWindow window;

View File

@@ -49,7 +49,7 @@ void PPU::Background::render_mode7() {
} }
case 2: { case 2: {
if(px < 0 || px > 1023 || py < 0 || py > 1023) { if((px | py) & ~1023) {
palette = 0; palette = 0;
} else { } else {
px &= 1023; px &= 1023;
@@ -63,7 +63,7 @@ void PPU::Background::render_mode7() {
} }
case 3: { case 3: {
if(px < 0 || px > 1023 || py < 0 || py > 1023) { if((px | py) & ~1023) {
tile = 0; tile = 0;
} else { } else {
px &= 1023; px &= 1023;

View File

@@ -283,7 +283,7 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
switch(addr & 0xffff) { switch(addr & 0xffff) {
case 0x2100: { //INIDISP case 0x2100: { //INIDISP
if(regs.display_disable && vcounter() == display.height) oam.address_reset(); if(regs.display_disable && cpu.vcounter() == display.height) oam.address_reset();
regs.display_disable = data & 0x80; regs.display_disable = data & 0x80;
regs.display_brightness = data & 0x0f; regs.display_brightness = data & 0x0f;
return; return;

View File

@@ -115,7 +115,6 @@ void PPU::Background::serialize(serializer &s) {
s.integer(regs.main_enable); s.integer(regs.main_enable);
s.integer(regs.sub_enable); s.integer(regs.sub_enable);
s.integer(y);
s.integer(hires); s.integer(hires);
s.integer(width); s.integer(width);
@@ -132,6 +131,7 @@ void PPU::Background::serialize(serializer &s) {
s.integer(vscroll); s.integer(vscroll);
s.integer(mosaic_vcounter); s.integer(mosaic_vcounter);
s.integer(mosaic_voffset);
window.serialize(s); window.serialize(s);
} }

Some files were not shown because too many files have changed in this diff Show More