After this commit, SolveSpace deals with paths as follows:
* Paths are generally treated as opaque platform-specific strings.
This helps on Linux, because paths on Linux don't have any
specific encoding and it helps to avoid any operations on them.
* The UI in some places wants to get a basename. In this case,
the newly introduced PATH_SEP is used. This allows to treat
backslash as a regular character, which it is on Linux and OS X.
* The only place where any nontrivial operations on paths are
performed is the g->impFile/impFileRel logic.
Specifically, when saved, g->impFile always contains an absolute
path with separators of the current platform, and g->impFileRel
always contains a relative path with UNIX separators. This allows
to treat backslash as a regular character.
Old files will contain g->impFileRel with Windows separators;
these are detected by looking for a drive letter in g->impFile
and in that case mapping Windows separators to UNIX ones.
There is no need to treat UNIX separators (forward slashes) in
any special way on Windows because there is no way on Windows,
not even via UNC paths, to create or address a directory entry
with a forward slash in its name.
What do we gain from this? Several things.
* First, usage of PATH_MAX (the POSIX constant) is eliminated.
PATH_MAX is actually a lie; Linux and OS X (and probably other BSDs
too) do not have an actual path length limit. Linux claims 4096,
OS X claims 1024, but it is trivial to construct paths that are
longer.
* Second, while Windows does enforce a limit of MAX_PATH (the Win32
constant) for its ASCII functions, the Unicode variants, when
used with UNC paths, do not have this restriction.
The capability to use UNC paths is useful by itself, as it allows
to access files on network shares directly.
* Third, representing paths as std::string will make it easier to
interoperate with *W WinAPI functions later.
This is necessary to store non-POD classes in these containers.
Note that List and IdList do not use MemRealloc anymore;
this is necessarily (slightly) less efficient, but is the right
semantics, as you cannot just move non-POD types, e.g. std::string,
around in memory. All STL containers provide the same guarantees
and share the performance hit.
The slowdown is mostly mitigated by moving the contained objects,
so that no additional heap allocations or copies occur beyond
that of the object itself.
This is required to avoid name conflicts with the Cocoa libraries
on OS X.
I renamed the `class SolveSpace` to `class SolveSpaceUI`, because
that's what it does, and because otherwise the namespace would
have to be called something else than `namespace SolveSpace`.
In principle, GTK3 is the way forward, and GTK2 is officially
deprecated, though still maintained. In practice however, GTK3
is often unbearably buggy; e.g. on my system, combo boxes
don't ever roll up in GTK3 windows. So I have added support
for both.
This required a few minor changes to the core, namely:
* GTK wants to know beforehand whether a menu item is a check
menu item or a regular one.
* GTK doesn't give us an easy way to execute something after
any event is processed, so an explicit idle timer is added.
This is a no-op on Win32.
* A few function signatures were const'ed, since GTK expects
immutable strings when converting to Glib::ustring.
fltkutil.cpp should be independent of FLTK so that it can be linked
into libslvs while neither requiring every user of the library to
reimplement these support routines nor requiring linking in FLTK.