* Added clipboard support (issue #60)

* Fixed keyboard shortcuts while code editing in game
dev-ui
erihel 2013-04-11 13:37:15 +02:00
parent 99d386b61a
commit 01309c8bd0
16 changed files with 2047 additions and 169 deletions

View File

@ -181,6 +181,13 @@ else()
endif()
##
# Clipboard support
##
set(CLIPBOARD_DIR ${colobot_SOURCE_DIR}/lib/clipboard/include)
add_subdirectory(${colobot_SOURCE_DIR}/lib/clipboard bin/clipboard)
##
# Doxygen docs
##

View File

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 2.8)
include_directories(. include/clipboard)
add_definitions(-DLIB_COMPILE=1)
if (${PLATFORM_WINDOWS})
set(CLIPBOARD_SRC src/clipboardWin32.c)
elseif (${PLATFORM_LINUX})
set(CLIPBOARD_SRC src/clipboardX11.c)
else()
set(CLIPBOARD_SRC src/clipboardX11.c)
endif()
include_directories(${SDL_INCLUDE_DIR})
add_library(clipboard STATIC src/utf.c ${CLIPBOARD_SRC})

View File

@ -0,0 +1,72 @@
Warzone 2100 Source & Data
--------------------------
This document replaces the file "readme.txt" as present in the Warzone 2100 GPL
release of December 6th 2004.
1) These source and data files are provided as is with no guarantees:
- No assistance or support will be offered or given.
- Everything you will require to make a build of the game should be here. If
it isn't, you'll have to improvise.
- None of us here at Pivotal Games are in a position to be able to offer any
help with making this work.
2) Everything included (source code and data), as well as the not included
videos and music, is released under the terms of the GNU General Public
License, version 2 or (at your option) any later version.
Please be sure to read the entirety of this license, but the summary is that
you're free to do what you want with the source subject to making the full
source code freely available in the event of the distribution of new
binaries.
3) Following exception to the GPL is granted:
------
Linking Warzone 2100 statically or dynamically with other modules is making
a combined work based on Warzone 2100. Thus, the terms and conditions of
the GNU General Public License cover the whole combination.
In addition, as a special exception, the copyright holders of Warzone 2100
give you permission to combine Warzone 2100 with code included in the
standard release of libraries that are accessible, redistributable and
linkable free of charge. You may copy and distribute such a system
following the terms of the GNU GPL for Warzone 2100 and the licenses of the
other code concerned.
Note that people who make modified versions of Warzone 2100 are not
obligated to grant this special exception for their modified versions; it
is their choice whether to do so. The GNU General Public License gives
permission to release a modified version without this exception; this
exception also makes it possible to release a modified version which
carries forward this exception.
------
4) Permission is granted to use the name "Warzone 2100", the logos, stories,
texts and related materials.
5) Permission is granted to copy and distribute unaltered copies and/or images
of the original game discs in any medium, provided that they are distributed
free of charge and retain their original copyright and trademark notices.
Finally, the primary motivation for this release is for entertainment and
educational purposes. On the subject of the latter, don't be surprised to see
some pretty gnarly old-school C code in here; the game was a classic, but large
areas of the code aren't pretty; OO design and C++ evangelists beware! We
haven't spent any time cleaning the code or making it pretty - what you see is
what you're getting, warts n' all.
Thank you to Jonathan Kemp of Eidos Europe for permitting the release. Thanks to
Martin Severn for allowing to use his soundtrack. Thanks to Jason Walker for
helping to facilitate the release of the movies and sound tracks, as well as
clarifying the meaning of this license. Thanks also to Frank Lamboy for
assistance with the release and for campaigning along with many many others
over the years for the source to be made available.
The correspondence, online petitions and persistence made this possible. We were
constantly amazed at the community support for Warzone even after all this
time; it's nice to be able to give something back, assuming you can get it to
compile... ;-)
Original - 6th December 2004
Alex M - ex Pumpkin Studios (Eidos)
Amended - 10th June 2008
Jason W - Eidos

View File

@ -0,0 +1,55 @@
/*
This file is part of Warzone 2100.
Copyright (C) 2008 Freddie Witherden
Copyright (C) 2008-2009 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef CLIPBOARD_H_
#define CLIPBOARD_H_
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Returns a copy of the text in the systems clipboard. Should the clipboard be
* empty, or populated with non-textual data NULL is returned. The character set
* of the returned is guaranteed to be UTF-8.
*
* It remains the responsibility of the caller to free() the string when
* finished with it.
*
* @return The textual contents of the clipboard (if any), otherwise NULL.
*/
char *widgetGetClipboardText(void);
/**
* Attempts to set the contents of the systems clipboard to text. The character
* set of text must be UTF-8.
*
* @param text The UTF-8 text to set the clipboard to.
* @return True if the contents were successfully set, false otherwise.
*/
bool widgetSetClipboardText(const char *text);
#ifdef __cplusplus
}
#endif
#endif /*CLIPBOARD_H_*/

View File

@ -0,0 +1,100 @@
/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2009 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*! \file
* \brief Simple type definitions.
*/
#ifndef __INCLUDED_LIB_FRAMEWORK_TYPES_H__
#define __INCLUDED_LIB_FRAMEWORK_TYPES_H__
#include "wzglobal.h"
#ifdef HAVE_INTTYPES_H // defined WZ_C99
/* Compilers that have support for C99 have all values below defined in stdint.h */
# include <inttypes.h>
#else
// Defines C99 types for C99 incompatible compilers (e.g. MSVC)
#include <SDL_stdinc.h>
#ifndef WZ_CC_MINGW
# define INT8_MIN (-128)
# define INT16_MIN (-32767-1)
# define INT32_MIN (-2147483647-1)
# define INT8_MAX (127)
# define INT16_MAX (32767)
# define INT32_MAX (2147483647)
# define UINT8_MAX (255)
# define UINT16_MAX (65535)
# define UINT32_MAX (4294967295U)
#endif
#ifdef WZ_CC_MSVC
# define PRIu32 "u"
# define PRIu64 "I64u"
typedef SSIZE_T ssize_t;
#endif
#endif // WZ_C99
#include <limits.h>
#include <ctype.h>
/* Basic numeric types */
typedef uint8_t UBYTE;
typedef int8_t SBYTE;
typedef uint16_t UWORD;
typedef int16_t SWORD;
typedef uint32_t UDWORD;
typedef int32_t SDWORD;
/* Numeric size defines */
#define UBYTE_MAX UINT8_MAX
#define SBYTE_MIN INT8_MIN
#define SBYTE_MAX INT8_MAX
#define UWORD_MAX UINT16_MAX
#define SWORD_MIN INT16_MIN
#define SWORD_MAX INT16_MAX
#define UDWORD_MAX UINT32_MAX
#define SDWORD_MIN INT32_MIN
#define SDWORD_MAX INT32_MAX
// If we are C99 compatible, the "bool" macro will be defined in <stdbool.h> (as _Bool)
// C++ comes with an integrated bool type
#if defined(WZ_CXX98)
#elif defined(WZ_C99)
# include <stdbool.h>
#else
// Pretend we are C99 compatible (well, for the bool type then)
# ifndef bool
# define bool BOOL
# endif
# ifndef true
# define true (1)
# endif
# ifndef false
# define false (0)
# endif
# ifndef __bool_true_false_are_defined
# define __bool_true_false_are_defined (1)
# endif
#endif /* WZ_C99 */
#if !defined(WZ_OS_WIN)
typedef int BOOL;
#endif // WZ_OS_WIN
#endif // __INCLUDED_LIB_FRAMEWORK_TYPES_H__

View File

@ -0,0 +1,115 @@
/*
This file is part of Warzone 2100.
Copyright (C) 2007 Giel van Schijndel
Copyright (C) 2007-2009 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
$Revision: 9336 $
$Id: utf.h 9336 2010-01-18 19:10:17Z cypr $
$HeadURL: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk/lib/framework/utf.h $
*/
#ifndef __INCLUDE_LIB_FRAMEWORK_UTF8_H__
#define __INCLUDE_LIB_FRAMEWORK_UTF8_H__
/* Allow frame header files to be singly included */
#define FRAME_LIB_INCLUDE
#include "types.h"
#ifdef __cplusplus
extern "C"
{
#endif //__cplusplus
/** Used to store a UTF-32 character in
*/
typedef uint32_t utf_32_char;
/** Used to store a UTF-16 character in (this is <em>not</em> necessarily a
* full Unicode codepoint)
*/
typedef uint16_t utf_16_char;
/** Decodes a single Unicode character from the given UTF-16 string.
*
* \param utf16_char Points to a character string that should contain at
* least one valid UTF-16 character sequence.
* \param[out] next_char Will be modified to point to the first character
* following the UTF-16 character sequence.
*
* \return The Unicode character encoded as UTF-32 with native endianness.
*/
utf_32_char UTF16DecodeChar(const utf_16_char *utf16_char, const utf_16_char **next_char);
/** Decodes a single Unicode character from the given UTF-8 string.
*
* \param utf8_char Points to a character string that should contain at
* least one valid UTF-8 character sequence.
* \param[out] next_char Will be modified to point to the first character
* following the UTF-8 character sequence.
*
* \return The Unicode character encoded as UTF-32 with native endianness.
*/
utf_32_char UTF8DecodeChar(const char *utf8_char, const char **next_char);
/** Determines the amount of unicode codepoints in a UTF-8 encoded string
* \param utf8_string the UTF-8 encoded string to count
* \return the amount of codepoints found in the UTF-8 string
*/
size_t UTF8CharacterCount(const char *utf8_string);
size_t UTF16CharacterCount(const uint16_t *utf16);
/** Encodes a UTF-16 encoded unicode string to a UTF-8 encoded string
* \param unicode_string the UTF-16 encoded unicode string to encode into UTF-8
* \param[out] nbytes the number of bytes allocated, may be NULL
* \return a UTF-8 encoded unicode nul terminated string (use free() to deallocate it)
*/
char *UTF16toUTF8(const utf_16_char *unicode_string, size_t *nbytes);
/** Decodes a UTF-8 encoded string to a UTF-16 encoded string (native endianess)
* \param utf8_string a UTF-8 encoded nul terminated string
* \param[out] nbytes the number of bytes allocated, may be NULL
* \return a UTF-16 encoded unicode nul terminated string (use free() to deallocate it)
*/
utf_16_char *UTF8toUTF16(const char *utf8_string, size_t *nbytes);
char *UTF8CharacterAtOffset(const char *utf8_string, size_t index);
utf_16_char *UTF16CharacterAtOffset(const utf_16_char *utf16_string, size_t index);
/** Encodes a UTF-32 string to a UTF-8 encoded string
* \param unicode_string the UTF-32 string to encode into UTF-8
* \param[out] nbytes the number of bytes allocated, may be NULL
* \return a UTF-8 encoded unicode nul terminated string (use free() to deallocate it)
*/
char *UTF32toUTF8(const utf_32_char *unicode_string, size_t *nbytes);
/** Decodes a UTF-8 encoded string to a UTF-32 string
* \param utf8_string a UTF-8 encoded nul terminated string
* \param[out] nbytes the number of bytes allocated, may be NULL
* \return a UTF-32 nul terminated string (use free() to deallocate it)
*/
utf_32_char *UTF8toUTF32(const char *utf8_string, size_t *nbytes);
/** Returns number of characters, not including terminating nul. */
size_t utf32len(const utf_32_char *unicode_string);
#ifdef __cplusplus
}
#endif //__cplusplus
#endif // __INCLUDE_LIB_FRAMEWORK_UTF8_H__

View File

@ -0,0 +1,614 @@
/*
This file is part of Warzone 2100.
Copyright (C) 1992-2007 Trolltech ASA.
Copyright (C) 2005-2009 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*! \file wzglobal.h
* \brief Platform detection, workarounds and compat fixes
*
* OS and CC detection code shamelessly stolen from Qt4 (Qt/qglobal.h) by Dennis.
* This has been stripped down, feel free to add checks as you need them.
*/
#ifndef WZGLOBAL_H
#define WZGLOBAL_H
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#if defined(HAVE_CONFIG_H)
# undef _XOPEN_SOURCE
# include "config.h"
#elif defined(__MACOSX__)
# include "config-macosx.h"
#endif
/* ---- Platform detection ---- */
/*
The operating system, must be one of: (WZ_OS_x)
DARWIN - Darwin OS (synonym for WZ_OS_MAC)
OS2 - OS/2
OS2EMX - XFree86 on OS/2 (not PM)
WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP)
CYGWIN - Cygwin
SOLARIS - Sun Solaris
HPUX - HP-UX
ULTRIX - DEC Ultrix
LINUX - Linux
FREEBSD - FreeBSD
GNU_kFREEBSD - GNU/kFreeBSD
NETBSD - NetBSD
OPENBSD - OpenBSD
BSDI - BSD/OS
IRIX - SGI Irix
OSF - HP Tru64 UNIX
SCO - SCO OpenServer 5
UNIXWARE - UnixWare 7, Open UNIX 8
AIX - AIX
HURD - GNU Hurd
DGUX - DG/UX
RELIANT - Reliant UNIX
DYNIX - DYNIX/ptx
QNX - QNX
QNX6 - QNX RTP 6.1
LYNX - LynxOS
BSD4 - Any BSD 4.4 system
UNIX - Any UNIX BSD/SYSV system
*/
#if defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__))
# define WZ_OS_DARWIN
# define WZ_OS_BSD4
# ifdef __LP64__
# define WZ_OS_DARWIN64
# else
# define WZ_OS_DARWIN32
# endif
#elif defined(__CYGWIN__)
# define WZ_OS_CYGWIN
#elif defined(__OS2__)
# if defined(__EMX__)
# define WZ_OS_OS2EMX
# else
# define WZ_OS_OS2
# endif
#elif !defined(SAG_COM) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
# define WZ_OS_WIN32
# define WZ_OS_WIN64
#elif !defined(SAG_COM) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
# define WZ_OS_WIN32
#elif defined(__MWERKS__) && defined(__INTEL__)
# define WZ_OS_WIN32
#elif defined(__sun) || defined(sun)
# define WZ_OS_SOLARIS
#elif defined(hpux) || defined(__hpux)
# define WZ_OS_HPUX
#elif defined(__ultrix) || defined(ultrix)
# define WZ_OS_ULTRIX
#elif defined(sinix)
# define WZ_OS_RELIANT
#elif defined(__linux__) || defined(__linux)
# define WZ_OS_LINUX
#elif defined(__FreeBSD__) || defined(__DragonFly__)
# define WZ_OS_FREEBSD
# define WZ_OS_BSD4
#elif defined(__FreeBSD_kernel__) && !defined(__FreeBSD__)
/* We're running a non-FreeBSD system with a FreeBSD kernel. Find out what C
* library we're using to detect the system we're running on. */
# include <stdlib.h>
# if defined(__GLIBC__)
/* We're running GNU/kFreeBSD */
# define WZ_OS_GNU_kFREEBSD
# endif
#elif defined(__NetBSD__)
# define WZ_OS_NETBSD
# define WZ_OS_BSD4
#elif defined(__OpenBSD__)
# define WZ_OS_OPENBSD
# define WZ_OS_BSD4
#elif defined(__bsdi__)
# define WZ_OS_BSDI
# define WZ_OS_BSD4
#elif defined(__sgi)
# define WZ_OS_IRIX
#elif defined(__osf__)
# define WZ_OS_OSF
#elif defined(_AIX)
# define WZ_OS_AIX
#elif defined(__Lynx__)
# define WZ_OS_LYNX
#elif defined(__GNU__)
# define WZ_OS_HURD
#elif defined(__DGUX__)
# define WZ_OS_DGUX
#elif defined(__QNXNTO__)
# define WZ_OS_QNX6
#elif defined(__QNX__)
# define WZ_OS_QNX
#elif defined(_SEQUENT_)
# define WZ_OS_DYNIX
#elif defined(_SCO_DS) /* SCO OpenServer 5 + GCC */
# define WZ_OS_SCO
#elif defined(__USLC__) /* all SCO platforms + UDK or OUDK */
# define WZ_OS_UNIXWARE
#elif defined(__svr4__) && defined(i386) /* Open UNIX 8 + GCC */
# define WZ_OS_UNIXWARE
#elif defined(__INTEGRITY)
# define WZ_OS_INTEGRITY
#elif defined(__MAKEDEPEND__)
#else
# error "Warzone has not been tested on this OS. Please contact warzone-dev@gna.org"
#endif /* WZ_OS_x */
#if defined(WZ_OS_WIN32) || defined(WZ_OS_WIN64)
# define WZ_OS_WIN
#endif /* WZ_OS_WIN32 */
#if defined(WZ_OS_DARWIN)
# define WZ_OS_MAC /* WZ_OS_MAC is mostly for compatibility, but also more clear */
# define WZ_OS_MACX /* WZ_OS_MACX is only for compatibility.*/
# if defined(WZ_OS_DARWIN64)
# define WZ_OS_MAC64
# elif defined(WZ_OS_DARWIN32)
# define WZ_OS_MAC32
# endif
#endif /* WZ_OS_DARWIN */
#if defined(WZ_OS_MSDOS) || defined(WZ_OS_OS2) || defined(WZ_OS_WIN)
# undef WZ_OS_UNIX
#elif !defined(WZ_OS_UNIX)
# define WZ_OS_UNIX
#endif /* WZ_OS_* */
/*
The compiler, must be one of: (WZ_CC_x)
MSVC - Microsoft Visual C/C++, Intel C++ for Windows
GNU - GNU C++
CLANG - Clang LLVM
INTEL - Intel C++ for Linux, Intel C++ for Windows
TINYC - Fabrice Bellard's Tiny C Compiler
Should be sorted most to least authoritative.
*/
#if defined(_MSC_VER)
# define WZ_CC_MSVC
/* All ISO C89 compliant compilers _should_ define the macro __STDC__, MSVC
* however is known _not_ to do this, so work around that here. */
# if !defined(__STDC__)
# define __STDC__ 1
# endif
/* Visual C++.Net issues for _MSC_VER >= 1300 */
# if _MSC_VER >= 1300
# define WZ_CC_MSVC_NET
# endif
/* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */
# if defined(__INTEL_COMPILER)
# define WZ_CC_INTEL
# endif
/* x64 does not support mmx intrinsics on windows */
# if (defined(ZS_OS_WIN64) && defined(_M_X64))
# undef ZS_HAVE_SSE
# undef ZS_HAVE_SSE2
# undef ZS_HAVE_MMX
# undef ZS_HAVE_3DNOW
# endif
#elif defined(__GNUC__)
# define WZ_CC_GNU
# if defined(__MINGW32__)
# define WZ_CC_MINGW
# endif
# if defined(__INTEL_COMPILER)
/* Intel C++ also masquerades as GCC 3.2.0 */
# define WZ_CC_INTEL
# endif
# if defined(__llvm__)
# define WZ_CC_LLVM
# endif
# if defined(__clang__)
# define WZ_CC_CLANG
# endif
/* Clang may not always masquerade as gcc */
#elif defined(__clang__)
# define WZ_CC_CLANG
# define WZ_CC_LLVM
#elif defined(__TINYC__)
# define WZ_CC_TINYC
#else
# error "Warzone has not been tested on this compiler. Please contact warzone-dev@gna.org"
#endif /* WZ_CC_x */
/*
The window system, must be one of: (WZ_WS_x)
MACX - Mac OS X
WIN32 - Windows
X11 - X Window System
QNX - QNX
*/
#if defined(_WIN32_X11_)
# define WZ_WS_X11
#elif defined(WZ_OS_WIN32)
# define WZ_WS_WIN32
# if defined(WZ_OS_WIN64)
# define WZ_WS_WIN64
# endif
#elif defined(WZ_OS_MAC)
# define WZ_WS_MAC
# define WZ_WS_MACX
# if defined(WZ_OS_MAC64)
# define WZ_WS_MAC64
# elif defined(WZ_OS_MAC32)
# define WZ_WS_MAC32
# endif
#elif defined(WZ_OS_QNX)
# define WZ_WS_QNX
#elif defined(WZ_OS_UNIX)
# define WZ_WS_X11
#else
# error "Warzone has not been tested on this window system. Please contact warzone-dev@gna.org"
#endif /* WZ_WS_x */
#if defined(WZ_WS_WIN16) || defined(WZ_WS_WIN32)
# define WZ_WS_WIN
#endif
/*
The supported C standard, must be one of: (WZ_Cxx)
99 - ISO/IEC 9899:1999 / C99
*/
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
# define WZ_C99
#endif /* WZ_Cxx */
/*
The supported C++ standard, must be one of: (WZ_CXXxx)
98 - ISO/IEC 14882:1998 / C++98
*/
#if defined(__cplusplus)
# define WZ_CXX98
#endif /* WZ_CXXxx */
/*
Convenience macros to test the versions of gcc.
Copied from glibc's features.h.
*/
#if defined(WZ_CC_GNU) && defined __GNUC__ && defined __GNUC_MINOR__
# define WZ_CC_GNU_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
# define WZ_CC_GNU_PREREQ(maj, min) 0
#endif
/*
Convenience macros to test the versions of icc.
*/
#if defined(WZ_CC_INTEL) && defined __ICC
# define WZ_CC_INTEL_PREREQ(maj, min) \
((__ICC) >= ((maj) * 100) + (min))
#else
# define WZ_CC_INTEL_PREREQ(maj, min) 0
#endif
/* ---- Declaration attributes ---- */
/*!
* \def WZ_DECL_DEPRECATED
*
* The WZ_DECL_DEPRECATED macro can be used to trigger compile-time warnings
* with newer compilers when deprecated functions are used.
*
* For non-inline functions, the macro gets inserted at front of the
* function declaration, right before the return type:
*
* \code
* WZ_DECL_DEPRECATED void deprecatedFunctionA();
* WZ_DECL_DEPRECATED int deprecatedFunctionB() const;
* \endcode
*
* For functions which are implemented inline,
* the WZ_DECL_DEPRECATED macro is inserted at the front, right before the return
* type, but after "static", "inline" or "virtual":
*
* \code
* WZ_DECL_DEPRECATED void deprecatedInlineFunctionA() { .. }
* virtual WZ_DECL_DEPRECATED int deprecatedInlineFunctionB() { .. }
* static WZ_DECL_DEPRECATED bool deprecatedInlineFunctionC() { .. }
* inline WZ_DECL_DEPRECATED bool deprecatedInlineFunctionD() { .. }
* \endcode
*
* You can also mark whole structs or classes as deprecated, by inserting the
* WZ_DECL_DEPRECATED macro after the struct/class keyword, but before the
* name of the struct/class:
*
* \code
* class WZ_DECL_DEPRECATED DeprecatedClass { };
* struct WZ_DECL_DEPRECATED DeprecatedStruct { };
* \endcode
*
* \note
* Description copied from KDE4, code copied from Qt4.
*
*/
#if WZ_CC_GNU_PREREQ(3,2) || WZ_CC_INTEL_PREREQ(10,0)
# define WZ_DECL_DEPRECATED __attribute__((__deprecated__))
#elif defined(WZ_CC_MSVC) && defined(WZ_CC_MSVC_NET)
# define WZ_DECL_DEPRECATED __declspec(deprecated)
#else
# define WZ_DECL_DEPRECATED
#endif
/*! \def WZ_DECL_FORMAT
* GCC: "The format attribute specifies that a function takes printf, scanf, strftime or strfmon
* style arguments which should be type-checked against a format string."
*/
#if WZ_CC_GNU_PREREQ(2,5) && !defined(WZ_CC_INTEL)
# define WZ_DECL_FORMAT(archetype, string_index, first_to_check) \
__attribute__((__format__(archetype, string_index, first_to_check)))
#else
# define WZ_DECL_FORMAT(archetype, string_index, first_to_check)
#endif
/*!
* \def WZ_DECL_NORETURN
* "A few standard library functions, such as abort and exit, cannot return. GCC knows this
* automatically. Some programs define their own functions that never return.
* You can declare them noreturn to tell the compiler this fact."
*/
#if WZ_CC_GNU_PREREQ(2,5) && !defined(WZ_CC_INTEL)
# define WZ_DECL_NORETURN __attribute__((__noreturn__))
#elif defined(WZ_CC_MSVC)
# define WZ_DECL_NORETURN __declspec(noreturn)
#else
# define WZ_DECL_NORETURN
#endif
/*!
* \def WZ_DECL_CONST
* GCC: "Many functions do not examine any values except their arguments, and have no effects
* except the return value. Basically this is just slightly more strict class than
* the pure attribute below, since function is not allowed to read global memory."
*/
#if WZ_CC_GNU_PREREQ(2,5) && !defined(WZ_CC_INTEL)
# define WZ_DECL_CONST __attribute__((__const__,__warn_unused_result__))
#else
# define WZ_DECL_CONST
#endif
/*!
* \def WZ_DECL_PURE
* GCC: "Many functions have no effects except the return value and their return value depends
* only on the parameters and/or global variables. Such a function can be subject to
* common subexpression elimination and loop optimization just as an arithmetic operator
* would be."
*/
#if WZ_CC_GNU_PREREQ(2,96) && !defined(WZ_CC_INTEL)
# define WZ_DECL_PURE __attribute__((__pure__))
#else
# define WZ_DECL_PURE
#endif
/*!
* \def WZ_DECL_UNUSED
* GCC: "This attribute, attached to a function, means that the function is meant to be possibly
* unused. GCC will not produce a warning for this function."
*/
#if WZ_CC_GNU_PREREQ(3,2) || WZ_CC_INTEL_PREREQ(10,0)
# define WZ_DECL_UNUSED __attribute__((__unused__))
#else
# define WZ_DECL_UNUSED
#endif
/*!
* \def WZ_DECL_WARN_UNUSED_RESULT
* GCC: "The warn_unused_result attribute causes a warning to be emitted if a caller of the
* function with this attribute does not use its return value. This is useful for
* functions where not checking the result is either a security problem or always a bug,
* such as realloc."
*/
#if defined(WZ_CC_GNU) && !defined(WZ_CC_INTEL)
# define WZ_DECL_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
#else
# define WZ_DECL_WARN_UNUSED_RESULT
#endif
/*! \def WZ_DECL_MAY_ALIAS
* GCC: "Accesses to objects with types with this attribute are not subjected to type-based alias
* analysis, but are instead assumed to be able to alias any other type of objects,
* just like the char type. See -fstrict-aliasing for more information on aliasing issues."
*/
#if WZ_CC_GNU_PREREQ(3,3) && !defined(WZ_CC_INTEL)
# define WZ_DECL_MAY_ALIAS __attribute__((__may_alias__))
#else
# define WZ_DECL_MAY_ALIAS
#endif
/*!
* \def WZ_DECL_RESTRICT
* Apply the "restrict" keyword found in the C99 revision of the standard.
* The compiler may assume that the memory referenced by a "restrict" pointer is not aliased
* by any other pointer. Thus this forms the opposite of WZ_DECL_MAY_ALIAS.
*/
#if defined(WZ_C99) && WZ_CC_GNU_PREREQ(4,1) && !defined(WZ_CC_INTEL)
# define WZ_DECL_RESTRICT restrict
#elif defined(WZ_CC_MSVC) && defined(WZ_CC_MSVC_NET)
# define WZ_DECL_RESTRICT __restrict
#else
# define WZ_DECL_RESTRICT
#endif
/*! \def WZ_DECL_THREAD
* Declares a variable to be local to the running thread, and not shared between threads.
*/
#if defined(WZ_CC_GNU) || defined(WZ_CC_INTEL)
# define WZ_DECL_THREAD __thread
#elif defined(WZ_CC_MSVC)
# define WZ_DECL_THREAD __declspec(thread)
#else
# error "Thread local storage attribute required"
#endif
/*! \def WZ_ASSERT_STATIC_STRING
* Asserts that the given string is statically allocated.
*/
#if defined(__cplusplus)
# include <typeinfo>
# define WZ_ASSERT_STATIC_STRING(_var) assert(typeid(_var) == typeid(char[sizeof(_var)]))
#elif defined(WZ_CC_GNU) || defined(WZ_CC_INTEL)
# define WZ_ASSERT_STATIC_STRING(_var) STATIC_ASSERT(__builtin_types_compatible_p(typeof(_var), char[]))
#else
# define WZ_ASSERT_STATIC_STRING(_var) (void)(_var)
#endif
/*! \def WZ_ASSERT_ARRAY
* Asserts that the given variable is a (statically sized) array, not just a pointer.
*/
#if defined(__cplusplus)
# define WZ_ASSERT_ARRAY_EXPR(a) 0
#elif defined(WZ_CC_GNU) || defined(WZ_CC_INTEL)
/* &a[0] degrades to a pointer: a different type from an array */
# define WZ_ASSERT_ARRAY_EXPR(a) STATIC_ASSERT_EXPR(!__builtin_types_compatible_p(typeof(a), typeof(&(a)[0])))
#else
# define WZ_ASSERT_ARRAY_EXPR(a) 0
#endif
#define WZ_ASSERT_ARRAY(a) (void)WZ_ASSERT_ARRAY_EXPR(a)
/* ---- Platform specific setup ---- */
#if defined(WZ_OS_WIN)
# if defined(WZ_CC_MINGW)
# include <unistd.h>
# include <sys/param.h>
# include <w32api.h>
# define _WIN32_IE IE5
// Required for alloca
# include <malloc.h>
# elif defined(WZ_CC_MSVC)
# if defined(_DEBUG)
# define DEBUG
# define _CRTDBG_MAP_ALLOC
# include <stdlib.h>
# include <crtdbg.h>
# endif /* _DEBUG */
# endif /* WZ_CC_* */
# define WIN32_LEAN_AND_MEAN
# define WIN32_EXTRA_LEAN
# undef NOMINMAX
# define NOMINMAX 1 // disable the min / max macros
# include <windows.h>
# if defined(WZ_CC_MSVC)
// notify people we are disabling these warning messages.
# pragma message (" *** Warnings 4018,4100,4127,4204,4244,4267,4389 have been squelched. ***")
# pragma warning (disable : 4018) // Shut up: '>' : signed/unsigned mismatch
# pragma warning (disable : 4100) // Shut up: unreferenced formal parameter (FIXME)
# pragma warning (disable : 4127) // Shut up: conditional expression is constant (eg. "while(0)")
# pragma warning (disable : 4204) // Shut up: non-constant aggregate initializer
# pragma warning (disable : 4244) // Shut up: conversion from 'float' to 'int', possible loss of data
# pragma warning (disable : 4267) // Shut up: conversion from 'size_t' to 'type', possible loss of data
# pragma warning (disable : 4389) // Shut up: '==' : signed/unsigned mismatch
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
# define inline __inline
# define alloca _alloca
# define fileno _fileno
# define isnan _isnan
# define isfinite _finite
# define PATH_MAX MAX_PATH
# endif /* WZ_CC_MSVC */
/* Make sure that PATH_MAX is large enough to use as the size for return
* buffers for Windows API calls
*/
# if (PATH_MAX < MAX_PATH)
# undef PATH_MAX
# define PATH_MAX MAX_PATH
# endif
#elif defined(WZ_OS_UNIX)
# include <unistd.h>
# if defined(HAVE_ALLOCA_H)
# include <alloca.h>
# endif
#endif /* WZ_OS_* */
// Define PATH_MAX for systems that don't have it, like Hurd
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#if !defined(WZ_C99) && !defined(va_copy)
/**
* Implements the interface of the C99 macro va_copy such that we can use it on
* non-C99 systems as well.
*
* This implementation assumes that va_list is just a pointer to the stack
* frame of the variadic function. This is by far the most common setup, though
* it might not always work.
*/
# define va_copy(dest, src) (void)((dest) = (src))
#endif // !WZ_C99 && !va_copy
#endif /* WZGLOBAL_H */

1
lib/clipboard/readme.txt Normal file
View File

@ -0,0 +1 @@
Source code in this directory was taken from Warzone2100 source. Please read COPING.README for licence or visit https://github.com/cybersphinx/wzgraphicsmods for more information.

View File

@ -0,0 +1,160 @@
/*
This file is part of Warzone 2100.
Copyright (C) 2008 Freddie Witherden
Copyright (C) 2008-2009 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "utf.h"
// Defines most macros and types from <stdbool.h> and <stdint.h>
#include "types.h"
char *widgetGetClipboardText()
{
uint16_t *clipboardText;
char *ourText = NULL;
// If there is any text on the clipboard, open it
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
{
// Get any text on the clipboard
HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT);
// If the handle is valid, fetch the text
if (hClipboardData)
{
// Get the text
clipboardText = GlobalLock(hClipboardData);
// So long as we got something
if (clipboardText)
{
int i, j;
// Convert it to UTF-8 (from UTF-16)
ourText = UTF16toUTF8(clipboardText, NULL);
// Unlock the text
GlobalUnlock(hClipboardData);
// Strip any '\r' from the text
for (i = j = 0; ourText[i]; i++)
{
if (ourText[i] != '\r')
{
ourText[j++] = ourText[i];
}
}
// NUL terminate
ourText[j] = '\0';
}
}
// Close the clipboard
CloseClipboard();
}
return ourText;
}
bool widgetSetClipboardText(const char *text)
{
bool ret = false;
// Copy of text with \n => \r\n
char *newText;
// UTF-16 version of newText
uint16_t *utf16NewText;
// Number of bytes utf16NewText is in size
size_t nbytes;
int count, i, j;
// Get the number of '\n' characters in the text
for (i = count = 0; text[i]; i++)
{
if (text[i] == '\n')
{
count++;
}
}
// Allocate enough space for the \r\n string
newText = malloc(strlen(text) + count + 1);
// Copy the string, converting \n to \r\n
for (i = j = 0; text[i]; i++, j++)
{
// If the character is a newline prepend a \r
if (text[i] == '\n')
{
newText[j++] = '\r';
}
// Copy the character (\n or otherwise)
newText[j] = text[i];
}
// NUL terminate
newText[j] = '\0';
// Convert to UTF-16
utf16NewText = UTF8toUTF16(newText, &nbytes);
// Open the clipboard
if (OpenClipboard(NULL))
{
HGLOBAL hGlobal;
uint16_t *clipboardText;
// Empty it (which also transfers ownership of it to ourself)
EmptyClipboard();
// Allocate global space for the text
hGlobal = GlobalAlloc(GMEM_MOVEABLE, nbytes);
// Lock the newly allocated memory
clipboardText = GlobalLock(hGlobal);
// Copy the text
memcpy(clipboardText, utf16NewText, nbytes);
// Unlock the memory (must come before CloseClipboard())
GlobalUnlock(hGlobal);
// Place the handle on the clipboard
if (SetClipboardData(CF_UNICODETEXT, hGlobal))
{
// We were successful
ret = true;
}
// Close the clipboard
CloseClipboard();
}
// Release the malloc-ed strings
free(newText);
free(utf16NewText);
return ret;
}

View File

@ -0,0 +1,293 @@
/*
This file is part of Warzone 2100.
Copyright (C) 2008 Freddie Witherden
Copyright (C) 2008-2009 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Something wicked this way comes...
* Documentation/reference:
* http://svr-www.eng.cam.ac.uk/~er258/code/dist/x_clipboard/paste.cc
*/
#include <stdbool.h>
#include <assert.h>
#include <SDL_syswm.h>
#include <SDL.h>
static SDL_SysWMinfo info;
// Atoms
static Atom XA_CLIPBOARD;
static Atom XA_COMPOUND_TEXT;
static Atom XA_UTF8_STRING;
static Atom XA_TARGETS;
/**
* Filters through SDL_Events searching for clipboard requests from the X
* server.
*
* @param evt The event to filter.
*/
static int widgetClipboardFilterX11(const SDL_Event *evt)
{
// We are only interested in window manager events
if (evt->type == SDL_SYSWMEVENT)
{
XEvent xevent = evt->syswm.msg->event.xevent;
// See if the event is a selection/clipboard request
if (xevent.type == SelectionRequest)
{
// Get the request in question
XSelectionRequestEvent *request = &xevent.xselectionrequest;
// Generate a reply to the selection request
XSelectionEvent reply;
reply.type = SelectionNotify;
reply.serial = xevent.xany.send_event;
reply.send_event = True;
reply.display = info.info.x11.display;
reply.requestor = request->requestor;
reply.selection = request->selection;
reply.property = request->property;
reply.target = None;
reply.time = request->time;
// They want to know what we can provide/offer
if (request->target == XA_TARGETS)
{
Atom possibleTargets[] =
{
XA_STRING,
XA_UTF8_STRING,
XA_COMPOUND_TEXT
};
XChangeProperty(info.info.x11.display, request->requestor,
request->property, XA_ATOM, 32, PropModeReplace,
(unsigned char *) possibleTargets, 3);
}
// They want a string (all we can provide)
else if (request->target == XA_STRING
|| request->target == XA_UTF8_STRING
|| request->target == XA_COMPOUND_TEXT)
{
int len;
char *xdata = XFetchBytes(info.info.x11.display, &len);
XChangeProperty(info.info.x11.display, request->requestor,
request->property, request->target, 8,
PropModeReplace, (unsigned char *) xdata,
len);
XFree(xdata);
}
else
{
// Did not have what they wanted, so no property set
reply.property = None;
}
// Dispatch the event
XSendEvent(request->display, request->requestor, 0, NoEventMask,
(XEvent *) &reply);
XSync(info.info.x11.display, False);
}
}
return 1;
}
static void widgetInitialiseClipboardX11()
{
static bool initialised = false;
if (!initialised)
{
// Get the window manager information
SDL_GetWMInfo(&info);
// Ensure we're running under X11
assert(info.subsystem == SDL_SYSWM_X11);
// Register the event filter
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
SDL_SetEventFilter(widgetClipboardFilterX11);
// Lock the connection to the X server
info.info.x11.lock_func();
// Get the clipboard atom (it is not defined by default)
XA_CLIPBOARD = XInternAtom(info.info.x11.display, "CLIPBOARD", True);
// Get the compound text type atom
XA_COMPOUND_TEXT = XInternAtom(info.info.x11.display, "COMPOUND_TEXT",
True);
// UTF-8 string atom
XA_UTF8_STRING = XInternAtom(info.info.x11.display, "UTF8_STRING",
True);
// TARGETS atom
XA_TARGETS = XInternAtom(info.info.x11.display, "TARGETS", True);
// Unlock the connection
info.info.x11.unlock_func();
// We are initialised
initialised = true;
}
}
char *widgetGetClipboardText()
{
char *text = NULL;
unsigned char *data = NULL;
Atom type;
int format, result;
unsigned long len, bytesLeft, dummy;
Window selectionOwner;
// Make sure we are initialised
widgetInitialiseClipboardX11();
// Lock the connection
info.info.x11.lock_func();
// Get the owner of the clipboard selection
selectionOwner = XGetSelectionOwner(info.info.x11.display, XA_CLIPBOARD);
// If there is a selection (and therefore owner) fetch it
if (selectionOwner != None)
{
SDL_Event event;
bool response = false;
/*
* Ask the window whom current owns the clipboard to convert it to an
* XA_UTF8_STRING and place it into the XA_CLIPBOARD property of our
* window.
*/
XConvertSelection(info.info.x11.display, XA_CLIPBOARD, XA_UTF8_STRING,
XA_CLIPBOARD, info.info.x11.window, CurrentTime);
XFlush(info.info.x11.display);
/*
* We now need to wait for a response from the window that owns the
* clipboard.
*/
// Unlock the connection so that the SDL event loop may function
info.info.x11.unlock_func();
while (!response)
{
// Wait for an event
SDL_WaitEvent(&event);
// If the event is a window manager event
if (event.type == SDL_SYSWMEVENT)
{
XEvent xevent = event.syswm.msg->event.xevent;
// See if it is a response to our request
if (xevent.type == SelectionNotify
&& xevent.xselection.requestor == info.info.x11.window)
{
response = true;
}
}
}
// Lock the connection once again
info.info.x11.lock_func();
// See how much data is there
XGetWindowProperty(info.info.x11.display, info.info.x11.window,
XA_CLIPBOARD, 0, 0, False, AnyPropertyType, &type,
&format, &len, &bytesLeft, &data);
// If any 0-length data was returned, free it
if (data)
{
XFree(data);
data = NULL;
}
// If there is any data
if (bytesLeft)
{
// Fetch the data
result = XGetWindowProperty(info.info.x11.display,
info.info.x11.window, XA_CLIPBOARD, 0,
bytesLeft, False, AnyPropertyType,
&type, &format, &len, &dummy, &data);
// If we got some data, duplicate it
if (result == Success)
{
text = strdup((char *) data);
XFree(data);
}
}
// Delete the property now that we are finished with it
XDeleteProperty(info.info.x11.display, info.info.x11.window,
XA_CLIPBOARD);
}
// Unlock the connection
info.info.x11.unlock_func();
return text;
}
bool widgetSetClipboardText(const char *text)
{
Window selectionOwner;
// Make sure we are initialised
widgetInitialiseClipboardX11();
// Lock the connection
info.info.x11.lock_func();
// Copy the text into the root windows cut buffer (for Xterm compatibility)
XStoreBytes(info.info.x11.display, text, strlen(text) + 1);
// Set ourself as the owner of the CLIPBOARD atom
XSetSelectionOwner(info.info.x11.display, XA_CLIPBOARD,
info.info.x11.window, CurrentTime);
// Check if we acquired ownership or not
selectionOwner = XGetSelectionOwner(info.info.x11.display, XA_CLIPBOARD);
// We got ownership
if (selectionOwner == info.info.x11.window)
{
info.info.x11.unlock_func();
return true;
}
// We did not get ownership
else
{
info.info.x11.unlock_func();
return false;
}
}

530
lib/clipboard/src/utf.c Normal file
View File

@ -0,0 +1,530 @@
/*
This file is part of Warzone 2100.
Copyright (C) 2007 Giel van Schijndel
Copyright (C) 2007-2009 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
$Revision: 9101 $
$Id: utf.c 9101 2010-01-10 13:11:55Z zarelsl $
$HeadURL: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk/lib/framework/utf.c $
*/
/** \file
* Functions to convert between different Unicode Transformation Formats (UTF for short)
*/
#include "utf.h"
#include <assert.h>
#include <stdlib.h>
#if defined(LIB_COMPILE)
# define ASSERT(expr, ...) (assert(expr))
# define debug(part, ...) ((void)0)
#else
# include "debug.h"
#endif
// Assert that non-starting octets are of the form 10xxxxxx
#define ASSERT_NON_START_OCTET(octet) \
assert((octet & 0xC0) == 0x80 && "invalid non-start UTF-8 octet")
// Assert that starting octets are either of the form 0xxxxxxx (ASCII) or 11xxxxxx
#define ASSERT_START_OCTECT(octet) \
assert((octet & 0x80) == 0x00 || (octet & 0xC0) == 0xC0 || !"invalid starting UTF-8 octet")
// Assert that hexadect (16bit sequence) 1 of UTF-16 surrogate pair sequences are of the form 110110XXXXXXXXXX
#define ASSERT_START_HEXADECT(hexadect) \
assert(((hexadect) & 0xD800) == 0xD800 && "invalid first UTF-16 hexadect")
// Assert that hexadect (16bit sequence) 2 of UTF-16 surrogate pair sequences are of the form 110111XXXXXXXXXX
#define ASSERT_FINAL_HEXADECT(hexadect) \
assert(((hexadect) & 0xDC00) == 0xDC00 && "invalid first UTF-16 hexadect")
utf_32_char UTF8DecodeChar(const char *utf8_char, const char **next_char)
{
utf_32_char decoded = '\0';
*next_char = utf8_char;
ASSERT_START_OCTECT(*utf8_char);
// first octect: 0xxxxxxx: 7 bit (ASCII)
if ((*utf8_char & 0x80) == 0x00)
{
// 1 byte long encoding
decoded = *((*next_char)++);
}
// first octect: 110xxxxx: 11 bit
else if ((*utf8_char & 0xe0) == 0xc0)
{
// 2 byte long encoding
ASSERT_NON_START_OCTET(utf8_char[1]);
decoded = (*((*next_char)++) & 0x1f) << 6;
decoded |= (*((*next_char)++) & 0x3f) << 0;
}
// first octect: 1110xxxx: 16 bit
else if ((*utf8_char & 0xf0) == 0xe0)
{
// 3 byte long encoding
ASSERT_NON_START_OCTET(utf8_char[1]);
ASSERT_NON_START_OCTET(utf8_char[2]);
decoded = (*((*next_char)++) & 0x0f) << 12;
decoded |= (*((*next_char)++) & 0x3f) << 6;
decoded |= (*((*next_char)++) & 0x3f) << 0;
}
// first octect: 11110xxx: 21 bit
else if ((*utf8_char & 0xf8) == 0xf0)
{
// 4 byte long encoding
ASSERT_NON_START_OCTET(utf8_char[1]);
ASSERT_NON_START_OCTET(utf8_char[2]);
ASSERT_NON_START_OCTET(utf8_char[3]);
decoded = (*((*next_char)++) & 0x07) << 18;
decoded |= (*((*next_char)++) & 0x3f) << 12;
decoded |= (*((*next_char)++) & 0x3f) << 6;
decoded |= (*((*next_char)++) & 0x3f) << 0;
}
else
{
// apparently this character uses more than 21 bit
// this decoder is not developed to cope with those
// characters so error out
ASSERT(!"out-of-range UTF-8 character", "this UTF-8 character is too large (> 21bits) for this UTF-8 decoder and too large to be a valid Unicode codepoint");
}
return decoded;
}
size_t UTF8CharacterCount(const char *utf8_string)
{
size_t length = 0;
while (*utf8_string != '\0')
{
UTF8DecodeChar(utf8_string, &utf8_string);
++length;
}
return length;
}
size_t UTF16CharacterCount(const uint16_t *utf16)
{
size_t length = 0;
while (*utf16)
{
UTF16DecodeChar(utf16, &utf16);
++length;
}
return length;
}
static size_t unicode_utf8_char_length(const utf_32_char unicode_char)
{
// an ASCII character, which uses 7 bit at most, which is one byte in UTF-8
if (unicode_char < 0x00000080)
return 1; // stores 7 bits
else if (unicode_char < 0x00000800)
return 2; // stores 11 bits
else if (unicode_char < 0x00010000)
return 3; // stores 16 bits
/* This encoder can deal with < 0x00200000, but Unicode only ranges
* from 0x0 to 0x10FFFF. Thus we don't accept anything else.
*/
else if (unicode_char < 0x00110000)
return 4; // stores 21 bits
/* Apparently this character lies outside the 0x0 - 0x10FFFF
* Unicode range, so don't accept it.
*/
ASSERT(!"out-of-range Unicode codepoint", "This Unicode codepoint is too large (%u > 0x10FFFF) to be a valid Unicode codepoint", (unsigned int)unicode_char);
// Dummy value to prevent warnings about missing return from function
return 0;
}
char *UTF8CharacterAtOffset(const char *utf8_string, size_t index)
{
while (*utf8_string != '\0'
&& index != 0)
{
// Move to the next character
UTF8DecodeChar(utf8_string, &utf8_string);
--index;
}
if (*utf8_string == '\0')
return NULL;
return (char*)utf8_string;
}
/** Encodes a single Unicode character to a UTF-8 encoded string.
*
* \param unicode_char A UTF-32 encoded Unicode codepoint that will be encoded
* into UTF-8. This should be a valid Unicode codepoint
* (i.e. ranging from 0x0 to 0x10FFFF inclusive).
* \param out_char Points to the position in a buffer where the UTF-8
* encoded character can be stored.
*
* \return A pointer pointing to the first byte <em>after</em> the encoded
* UTF-8 sequence. This can be used as the \c out_char parameter for a
* next invocation of encode_utf8_char().
*/
static char *encode_utf8_char(const utf_32_char unicode_char, char *out_char)
{
char *next_char = out_char;
// 7 bits
if (unicode_char < 0x00000080)
{
*(next_char++) = unicode_char;
}
// 11 bits
else if (unicode_char < 0x00000800)
{
// 0xc0 provides the counting bits: 110
// then append the 5 most significant bits
*(next_char++) = 0xc0 | (unicode_char >> 6);
// Put the next 6 bits in a byte of their own
*(next_char++) = 0x80 | (unicode_char & 0x3f);
}
// 16 bits
else if (unicode_char < 0x00010000)
{
// 0xe0 provides the counting bits: 1110
// then append the 4 most significant bits
*(next_char++) = 0xe0 | (unicode_char >> 12);
// Put the next 12 bits in two bytes of their own
*(next_char++) = 0x80 | ((unicode_char >> 6) & 0x3f);
*(next_char++) = 0x80 | (unicode_char & 0x3f);
}
// 21 bits
/* This encoder can deal with < 0x00200000, but Unicode only ranges
* from 0x0 to 0x10FFFF. Thus we don't accept anything else.
*/
else if (unicode_char < 0x00110000)
{
// 0xf0 provides the counting bits: 11110
// then append the 3 most significant bits
*(next_char++) = 0xf0 | (unicode_char >> 18);
// Put the next 18 bits in three bytes of their own
*(next_char++) = 0x80 | ((unicode_char >> 12) & 0x3f);
*(next_char++) = 0x80 | ((unicode_char >> 6) & 0x3f);
*(next_char++) = 0x80 | (unicode_char & 0x3f);
}
else
{
/* Apparently this character lies outside the 0x0 - 0x10FFFF
* Unicode range, so don't accept it.
*/
ASSERT(!"out-of-range Unicode codepoint", "This Unicode codepoint is too large (%u > 0x10FFFF) to be a valid Unicode codepoint", (unsigned int)unicode_char);
}
return next_char;
}
utf_32_char UTF16DecodeChar(const utf_16_char *utf16_char, const utf_16_char **next_char)
{
utf_32_char decoded;
*next_char = utf16_char;
// Are we dealing with a surrogate pair
if (*utf16_char >= 0xD800
&& *utf16_char <= 0xDFFF)
{
ASSERT_START_HEXADECT(utf16_char[0]);
ASSERT_FINAL_HEXADECT(utf16_char[1]);
decoded = (*((*next_char)++) & 0x3ff) << 10;
decoded |= *((*next_char)++) & 0x3ff;
decoded += 0x10000;
}
// Not a surrogate pair, so it's a valid Unicode codepoint right away
else
{
decoded = *((*next_char)++);
}
return decoded;
}
/** Encodes a single Unicode character to a UTF-16 encoded string.
*
* \param unicode_char A UTF-32 encoded Unicode codepoint that will be encoded
* into UTF-16. This should be a valid Unicode codepoint
* (i.e. ranging from 0x0 to 0x10FFFF inclusive).
* \param out_char Points to the position in a buffer where the UTF-16
* encoded character can be stored.
*
* \return A pointer pointing to the first byte <em>after</em> the encoded
* UTF-16 sequence. This can be used as the \c out_char parameter for a
* next invocation of encode_utf16_char().
*/
static utf_16_char *encode_utf16_char(const utf_32_char unicode_char, utf_16_char *out_char)
{
utf_16_char *next_char = out_char;
// 16 bits
if (unicode_char < 0x10000)
{
*(next_char++) = unicode_char;
}
else if (unicode_char < 0x110000)
{
const utf_16_char v = unicode_char - 0x10000;
*(next_char++) = 0xD800 | (v >> 10);
*(next_char++) = 0xDC00 | (v & 0x3ff);
ASSERT_START_HEXADECT(out_char[0]);
ASSERT_FINAL_HEXADECT(out_char[1]);
}
else
{
/* Apparently this character lies outside the 0x0 - 0x10FFFF
* Unicode range, and UTF-16 cannot cope with that, so error
* out.
*/
ASSERT(!"out-of-range Unicode codepoint", "This Unicode codepoint is too large (%u > 0x10FFFF) to be a valid Unicode codepoint", (unsigned int)unicode_char);
}
return next_char;
}
static size_t utf16_utf8_buffer_length(const utf_16_char* unicode_string)
{
const utf_16_char* curChar = unicode_string;
// Determine length of string (in octets) when encoded in UTF-8
size_t length = 0;
while (*curChar)
{
length += unicode_utf8_char_length(UTF16DecodeChar(curChar, &curChar));
}
return length;
}
char *UTF16toUTF8(const utf_16_char *unicode_string, size_t *nbytes)
{
const utf_16_char* curChar;
const size_t utf8_length = utf16_utf8_buffer_length(unicode_string);
// Allocate memory to hold the UTF-8 encoded string (plus a terminating nul char)
char* utf8_string = malloc(utf8_length + 1);
char* curOutPos = utf8_string;
if (utf8_string == NULL)
{
debug(LOG_ERROR, "Out of memory");
return NULL;
}
curChar = unicode_string;
while (*curChar)
{
curOutPos = encode_utf8_char(UTF16DecodeChar(curChar, &curChar), curOutPos);
}
// Terminate the string with a nul character
utf8_string[utf8_length] = '\0';
// Set the number of bytes allocated
if (nbytes)
{
*nbytes = utf8_length + 1;
}
return utf8_string;
}
static size_t utf8_as_utf16_buf_size(const char* utf8_string)
{
const char* curChar = utf8_string;
size_t length = 0;
while (*curChar != '\0')
{
const utf_32_char unicode_char = UTF8DecodeChar(curChar, &curChar);
if (unicode_char < 0x10000)
{
length += 1;
}
else if (unicode_char < 0x110000)
{
length += 2;
}
else
{
/* Apparently this character lies outside the 0x0 - 0x10FFFF
* Unicode range, and UTF-16 cannot cope with that, so error
* out.
*/
ASSERT(!"out-of-range Unicode codepoint", "This Unicode codepoint too large (%u > 0x10FFFF) for the UTF-16 encoding", (unsigned int)unicode_char);
}
}
return length;
}
utf_16_char *UTF8toUTF16(const char* utf8_string, size_t *nbytes)
{
const char* curChar = utf8_string;
const size_t unicode_length = utf8_as_utf16_buf_size(utf8_string);
// Allocate memory to hold the UTF-16 encoded string (plus a terminating nul)
utf_16_char* unicode_string = malloc(sizeof(utf_16_char) * (unicode_length + 1));
utf_16_char* curOutPos = unicode_string;
if (unicode_string == NULL)
{
debug(LOG_ERROR, "Out of memory");
return NULL;
}
while (*curChar != '\0')
{
curOutPos = encode_utf16_char(UTF8DecodeChar(curChar, &curChar), curOutPos);
}
// Terminate the string with a nul
unicode_string[unicode_length] = '\0';
// Set the number of bytes allocated
if (nbytes)
{
*nbytes = sizeof(utf_16_char) * (unicode_length + 1);
}
return unicode_string;
}
utf_16_char *UTF16CharacterAtOffset(const utf_16_char *utf16_string, size_t index)
{
while (*utf16_string != '\0'
&& index != 0)
{
// Move to the next character
UTF16DecodeChar(utf16_string, &utf16_string);
--index;
}
if (*utf16_string == '\0')
return NULL;
return (utf_16_char*)utf16_string;
}
static size_t utf32_utf8_buffer_length(const utf_32_char* unicode_string)
{
const utf_32_char* curChar;
// Determine length of string (in octets) when encoded in UTF-8
size_t length = 0;
for (curChar = unicode_string; *curChar != '\0'; ++curChar)
{
length += unicode_utf8_char_length(*curChar);
}
return length;
}
char *UTF32toUTF8(const utf_32_char *unicode_string, size_t *nbytes)
{
const utf_32_char* curChar;
const size_t utf8_length = utf32_utf8_buffer_length(unicode_string);
// Allocate memory to hold the UTF-8 encoded string (plus a terminating nul char)
char* utf8_string = malloc(utf8_length + 1);
char* curOutPos = utf8_string;
if (utf8_string == NULL)
{
debug(LOG_ERROR, "Out of memory");
return NULL;
}
for (curChar = unicode_string; *curChar != 0; ++curChar)
{
curOutPos = encode_utf8_char(*curChar, curOutPos);
}
// Terminate the string with a nul character
utf8_string[utf8_length] = '\0';
// Set the number of bytes allocated
if (nbytes)
{
*nbytes = utf8_length + 1;
}
return utf8_string;
}
utf_32_char *UTF8toUTF32(const char *utf8_string, size_t *nbytes)
{
const char* curChar = utf8_string;
const size_t unicode_length = UTF8CharacterCount(utf8_string);
// Allocate memory to hold the UTF-32 encoded string (plus a terminating nul)
utf_32_char* unicode_string = malloc(sizeof(utf_32_char) * (unicode_length + 1));
utf_32_char* curOutPos = unicode_string;
if (unicode_string == NULL)
{
debug(LOG_ERROR, "Out of memory");
return NULL;
}
while (*curChar != '\0')
{
*(curOutPos++) = UTF8DecodeChar(curChar, &curChar);
}
// Terminate the string with a nul
unicode_string[unicode_length] = '\0';
// Set the number of bytes allocated
if (nbytes)
{
*nbytes = sizeof(utf_32_char) * (unicode_length + 1);
}
return unicode_string;
}
size_t utf32len(const utf_32_char *unicode_string)
{
size_t ret = 0;
while (*unicode_string++)
++ret;
return ret;
}

View File

@ -196,6 +196,7 @@ ${Boost_LIBRARIES}
${LIBSNDFILE_LIBRARY}
${OPTIONAL_LIBS}
${PLATFORM_LIBS}
clipboard
)
# Local
@ -216,6 +217,7 @@ ${GLEW_INCLUDE_PATH}
${Boost_INCLUDE_DIRS}
${LIBSNDFILE_INCLUDE_DIR}
${OPTIONAL_INCLUDE_DIRS}
${CLIPBOARD_DIR}
)
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/CBot)

View File

@ -20,6 +20,8 @@
#include "app/app.h"
#include "clipboard/clipboard.h"
#include <string.h>
namespace Ui {
@ -298,55 +300,53 @@ bool CEdit::EventProcess(const Event &event)
bShift = ( (event.kmodState & KEY_MOD(SHIFT) ) != 0 );
bControl = ( (event.kmodState & KEY_MOD(CTRL) ) != 0);
if ( (event.key.unicode == 'X' && !bShift && bControl) ||
((event.kmodState & KEY_MOD(CTRL)) != 0 && bShift && !bControl) )
if ( (event.key.key == KEY(x) && !bShift && bControl) ||
(event.key.key == KEY(DELETE) && bShift && !bControl) )
{
Cut();
return true;
}
if ( (event.key.unicode == 'C' && !bShift && bControl) ||
((event.kmodState & KEY_MOD(CTRL)) != 0 && !bShift && bControl) )
if ( (event.key.key == KEY(c) && !bShift && bControl) ||
(event.key.key == KEY(INSERT) && !bShift && bControl) )
{
Copy();
return true;
}
if ( (event.key.unicode == 'V' && !bShift && bControl) ||
((event.kmodState & KEY_MOD(CTRL)) != 0 && bShift && !bControl) )
if ( (event.key.key == KEY(v) && !bShift && bControl) ||
(event.key.key == KEY(INSERT) && bShift && !bControl) )
{
Paste();
return true;
}
if ( event.key.unicode == 'A' && !bShift && bControl )
if ( event.key.key == KEY(a) && !bShift && bControl )
{
SetCursor(999999, 0);
return true;
}
if ( event.key.unicode == 'O' && !bShift && bControl )
if ( event.key.key == KEY(o) && !bShift && bControl )
{
Event newEvent(EVENT_STUDIO_OPEN);
// m_event->NewEvent(newEvent, EVENT_STUDIO_OPEN);
m_event->AddEvent(newEvent);
}
if ( event.key.unicode == 'S' && !bShift && bControl )
if ( event.key.key == KEY(s) && !bShift && bControl )
{
Event newEvent( EVENT_STUDIO_SAVE );
// m_event->MakeEvent(newEvent, EVENT_STUDIO_SAVE);
m_event->AddEvent(newEvent);
}
if ( event.key.unicode == 'Z' && !bShift && bControl )
if ( event.key.key == KEY(z) && !bShift && bControl )
{
Undo();
return true;
}
if ( event.key.unicode == 'U' && !bShift && bControl )
if ( event.key.key == KEY(u) && !bShift && bControl )
{
if ( MinMaj(false) ) return true;
}
if ( event.key.unicode == 'U' && bShift && bControl )
if ( event.key.key == KEY(u) && bShift && bControl )
{
if ( MinMaj(true) ) return true;
}
@ -2501,200 +2501,100 @@ void CEdit::ColumnFix()
// Cut the selected characters or entire line.
bool CEdit::Cut() // TODO MS Windows allocations
bool CEdit::Cut()
{
/* HGLOBAL hg;
char* text;
char c;
int c1, c2, start, len, i, j;
if ( !m_bEdit ) return false;
c1 = m_cursor1;
c2 = m_cursor2;
if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
if ( c1 == c2 )
{
while ( c1 > 0 )
{
if ( m_text[c1-1] == '\n' ) break;
c1 --;
}
while ( c2 < m_len )
{
c2 ++;
if ( m_text[c2-1] == '\n' ) break;
}
}
if ( c1 == c2 ) return false;
start = c1;
len = c2-c1;
if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
{
return false;
}
if ( !(text = (char*)GlobalLock(hg)) )
{
GlobalFree(hg);
return false;
}
j = 0;
for ( i=start ; i<start+len ; i++ )
{
c = m_text[i];
if ( c == '\n' ) text[j++] = '\r';
text[j++] = c;
}
text[j] = 0;
GlobalUnlock(hg);
if ( !OpenClipboard(NULL) )
{
GlobalFree(hg);
return false;
}
if ( !EmptyClipboard() )
{
GlobalFree(hg);
return false;
}
if ( !SetClipboardData(CF_TEXT, hg) )
{
GlobalFree(hg);
return false;
}
CloseClipboard();
UndoMemorize(OPERUNDO_SPEC);
m_cursor1 = c1;
m_cursor2 = c2;
Copy(true);
DeleteOne(0); // deletes the selected characters
Justif();
ColumnFix();
SendModifEvent();*/
SendModifEvent();
return true;
}
// Copy the selected characters or entire line.
bool CEdit::Copy() // TODO
bool CEdit::Copy(bool memorize_cursor)
{
/* HGLOBAL hg;
char* text;
char c;
int c1, c2, start, len, i, j;
int c1, c2, start, len;
char *text;
c1 = m_cursor1;
c2 = m_cursor2;
if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
if ( c1 > c2 ) {
Math::Swap(c1, c2); // always c1 <= c2
}
if ( c1 == c2 )
{
while ( c1 > 0 )
{
if ( m_text[c1-1] == '\n' ) break;
c1 --;
if ( c1 == c2 ) {
while ( c1 > 0 ) {
if ( m_text[c1 - 1] == '\n' ) {
break;
}
c1--;
}
while ( c2 < m_len )
{
c2 ++;
if ( m_text[c2-1] == '\n' ) break;
while ( c2 < m_len ) {
c2++;
if ( m_text[c2 - 1] == '\n' ) {
break;
}
}
}
if ( c1 == c2 ) return false;
if ( c1 == c2 ) {
return false;
}
start = c1;
len = c2-c1;
len = c2 - c1;
if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
{
return false;
}
if ( !(text = (char*)GlobalLock(hg)) )
{
GlobalFree(hg);
return false;
text = new char[len + 1];
strncpy(text, m_text + start, len);
text[len] = 0;
widgetSetClipboardText(text);
delete []text;
if (memorize_cursor) {
m_cursor1 = c1;
m_cursor2 = c2;
}
j = 0;
for ( i=start ; i<start+len ; i++ )
{
c = m_text[i];
if ( c == '\n' ) text[j++] = '\r';
text[j++] = c;
}
text[j] = 0;
GlobalUnlock(hg);
if ( !OpenClipboard(NULL) )
{
GlobalFree(hg);
return false;
}
if ( !EmptyClipboard() )
{
GlobalFree(hg);
return false;
}
if ( !SetClipboardData(CF_TEXT, hg) )
{
GlobalFree(hg);
return false;
}
CloseClipboard();
*/
return true;
}
// Paste the contents of the notebook.
bool CEdit::Paste() // TODO
bool CEdit::Paste()
{
/*HANDLE h;
char c;
char* p;
char* text;
if ( !m_bEdit ) return false;
if ( !OpenClipboard(NULL) )
{
if ( !m_bEdit ) {
return false;
}
if ( !(h = GetClipboardData(CF_TEXT)) )
{
CloseClipboard();
return false;
}
if ( !(p = (char*)GlobalLock(h)) )
{
CloseClipboard();
text = widgetGetClipboardText();
if ( text == nullptr ) {
return false;
}
UndoMemorize(OPERUNDO_SPEC);
while ( *p != 0 )
{
c = *p++;
if ( c == '\r' ) continue;
if ( c == '\t' && m_bAutoIndent ) continue;
for ( unsigned int i = 0; i < strlen(text); i++ ) {
c = text[i];
if ( c == '\r' ) {
continue;
}
if ( c == '\t' && m_bAutoIndent ) {
continue;
}
InsertOne(c);
}
GlobalUnlock(h);
CloseClipboard();
free(text);
Justif();
ColumnFix();
SendModifEvent();*/
SendModifEvent();
return true;
}
@ -2703,7 +2603,9 @@ bool CEdit::Paste() // TODO
bool CEdit::Undo()
{
if ( !m_bEdit ) return false;
if ( !m_bEdit ) {
return false;
}
return UndoRecall();
}
@ -2715,7 +2617,9 @@ void CEdit::Insert(char character)
{
int i, level, tab;
if ( !m_bEdit ) return;
if ( !m_bEdit ) {
return;
}
if ( !m_bMulti ) // single-line?
{

View File

@ -184,7 +184,7 @@ public:
bool GetMultiFont();
bool Cut();
bool Copy();
bool Copy(bool memorize_cursor = false);
bool Paste();
bool Undo();

View File

@ -204,6 +204,7 @@ ${GLEW_INCLUDE_PATH}
${Boost_INCLUDE_DIRS}
${OPTIONAL_INCLUDE_DIRS}
${LIBSNDFILE_INCLUDE_DIR}
${CLIPBOARD_DIR}
)
set(LIBS
@ -220,6 +221,7 @@ ${Boost_LIBRARIES}
${OPTIONAL_LIBS}
${PLATFORM_LIBS}
${LIBSNDFILE_LIBRARY}
clipboard
)
add_executable(colobot_ut ${COLOBOT_SOURCES} ${UT_SOURCES} ${OPENAL_SOURCES})

View File

@ -5,6 +5,7 @@ include_directories(
${SRC_DIR}
${GTEST_INCLUDE_DIR}
${GMOCK_INCLUDE_DIR}
${CLIPBOARD_DIR}
)
# Platform-dependent implementation of CSystemUtils
@ -12,8 +13,10 @@ if (${PLATFORM_WINDOWS})
set(SYSTEM_CPP_MODULE "system_windows.cpp")
elseif(${PLATFORM_LINUX})
set(SYSTEM_CPP_MODULE "system_linux.cpp")
set(ADDITIONAL_LIB X11)
else()
set(SYSTEM_CPP_MODULE "system_other.cpp")
set(ADDITIONAL_LIB X11)
endif()
add_executable(edit_test
@ -36,6 +39,9 @@ stubs/particle_stub.cpp
stubs/restext_stub.cpp
stubs/robotmain_stub.cpp
edit_test.cpp)
target_link_libraries(edit_test gtest gmock ${SDL_LIBRARY} ${SDLTTF_LIBRARY} ${Boost_LIBRARIES})
target_link_libraries(edit_test gtest gmock ${SDL_LIBRARY} ${SDLTTF_LIBRARY} ${Boost_LIBRARIES} ${ADDITIONAL_LIB} clipboard)
add_test(edit_test ./edit_test)