gosu 0.7.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (249) hide show
  1. data/COPYING.txt +29 -0
  2. data/Gosu/Async.hpp +48 -0
  3. data/Gosu/Audio.hpp +145 -0
  4. data/Gosu/AutoLink.hpp +16 -0
  5. data/Gosu/Bitmap.hpp +85 -0
  6. data/Gosu/ButtonsMac.hpp +114 -0
  7. data/Gosu/ButtonsWin.hpp +111 -0
  8. data/Gosu/ButtonsX.hpp +115 -0
  9. data/Gosu/Color.hpp +172 -0
  10. data/Gosu/Directories.hpp +36 -0
  11. data/Gosu/Font.hpp +59 -0
  12. data/Gosu/Fwd.hpp +31 -0
  13. data/Gosu/Gosu.hpp +26 -0
  14. data/Gosu/Graphics.hpp +86 -0
  15. data/Gosu/GraphicsBase.hpp +45 -0
  16. data/Gosu/IO.hpp +255 -0
  17. data/Gosu/Image.hpp +148 -0
  18. data/Gosu/ImageData.hpp +45 -0
  19. data/Gosu/Input.hpp +116 -0
  20. data/Gosu/Math.hpp +95 -0
  21. data/Gosu/Platform.hpp +61 -0
  22. data/Gosu/RotFlip.hpp +116 -0
  23. data/Gosu/Sockets.hpp +129 -0
  24. data/Gosu/Text.hpp +47 -0
  25. data/Gosu/TextInput.hpp +57 -0
  26. data/Gosu/Timing.hpp +16 -0
  27. data/Gosu/Utility.hpp +24 -0
  28. data/Gosu/WinUtility.hpp +76 -0
  29. data/Gosu/Window.hpp +84 -0
  30. data/GosuImpl/Async.cpp +37 -0
  31. data/GosuImpl/AudioFmod.cpp +417 -0
  32. data/GosuImpl/AudioSDL.cpp +255 -0
  33. data/GosuImpl/DirectoriesMac.mm +38 -0
  34. data/GosuImpl/DirectoriesUnix.cpp +48 -0
  35. data/GosuImpl/DirectoriesWin.cpp +42 -0
  36. data/GosuImpl/FileUnix.cpp +100 -0
  37. data/GosuImpl/FileWin.cpp +83 -0
  38. data/GosuImpl/Graphics/Bitmap.cpp +116 -0
  39. data/GosuImpl/Graphics/BitmapBMP.cpp +232 -0
  40. data/GosuImpl/Graphics/BitmapColorKey.cpp +39 -0
  41. data/GosuImpl/Graphics/BitmapPNG.cpp +276 -0
  42. data/GosuImpl/Graphics/BitmapUtils.cpp +67 -0
  43. data/GosuImpl/Graphics/BlockAllocator.cpp +127 -0
  44. data/GosuImpl/Graphics/BlockAllocator.hpp +34 -0
  45. data/GosuImpl/Graphics/Color.cpp +126 -0
  46. data/GosuImpl/Graphics/Common.hpp +21 -0
  47. data/GosuImpl/Graphics/DrawOp.hpp +154 -0
  48. data/GosuImpl/Graphics/Font.cpp +110 -0
  49. data/GosuImpl/Graphics/Graphics.cpp +295 -0
  50. data/GosuImpl/Graphics/Image.cpp +159 -0
  51. data/GosuImpl/Graphics/LargeImageData.cpp +115 -0
  52. data/GosuImpl/Graphics/LargeImageData.hpp +37 -0
  53. data/GosuImpl/Graphics/RotFlip.cpp +184 -0
  54. data/GosuImpl/Graphics/TexChunk.cpp +77 -0
  55. data/GosuImpl/Graphics/TexChunk.hpp +40 -0
  56. data/GosuImpl/Graphics/Text.cpp +223 -0
  57. data/GosuImpl/Graphics/TextMac.cpp +242 -0
  58. data/GosuImpl/Graphics/TextPangoFT.cpp +186 -0
  59. data/GosuImpl/Graphics/TextWin.cpp +172 -0
  60. data/GosuImpl/Graphics/Texture.cpp +104 -0
  61. data/GosuImpl/Graphics/Texture.hpp +34 -0
  62. data/GosuImpl/IO.cpp +48 -0
  63. data/GosuImpl/InputMac.mm +677 -0
  64. data/GosuImpl/InputWin.cpp +444 -0
  65. data/GosuImpl/InputX.cpp +158 -0
  66. data/GosuImpl/MacUtility.hpp +48 -0
  67. data/GosuImpl/Math.cpp +49 -0
  68. data/GosuImpl/RubyGosu.swg +474 -0
  69. data/GosuImpl/RubyGosuStub.mm +17 -0
  70. data/GosuImpl/RubyGosu_DllMain.cxx +30 -0
  71. data/GosuImpl/RubyGosu_wrap.cxx +8521 -0
  72. data/GosuImpl/RubyGosu_wrap.h +31 -0
  73. data/GosuImpl/Sockets/CommSocket.cpp +304 -0
  74. data/GosuImpl/Sockets/ListenerSocket.cpp +60 -0
  75. data/GosuImpl/Sockets/MessageSocket.cpp +136 -0
  76. data/GosuImpl/Sockets/Socket.cpp +145 -0
  77. data/GosuImpl/Sockets/Sockets.hpp +66 -0
  78. data/GosuImpl/TextInputMac.mm +207 -0
  79. data/GosuImpl/TextInputWin.cpp +197 -0
  80. data/GosuImpl/TextInputX.cpp +201 -0
  81. data/GosuImpl/TextTTFWin.cpp +247 -0
  82. data/GosuImpl/TimingUnix.cpp +17 -0
  83. data/GosuImpl/TimingWin.cpp +28 -0
  84. data/GosuImpl/Utility.cpp +140 -0
  85. data/GosuImpl/WinMain.cpp +69 -0
  86. data/GosuImpl/WinUtility.cpp +137 -0
  87. data/GosuImpl/WindowMac.mm +466 -0
  88. data/GosuImpl/WindowWin.cpp +447 -0
  89. data/GosuImpl/WindowX.cpp +392 -0
  90. data/GosuImpl/X11vroot.h +118 -0
  91. data/README.txt +13 -0
  92. data/Rakefile +178 -0
  93. data/examples/ChipmunkIntegration.rb +275 -0
  94. data/examples/CptnRuby.rb +231 -0
  95. data/examples/MoreChipmunkAndRMagick.rb +155 -0
  96. data/examples/OpenGLIntegration.rb +232 -0
  97. data/examples/RMagickIntegration.rb +449 -0
  98. data/examples/TextInput.cpp +170 -0
  99. data/examples/TextInput.rb +139 -0
  100. data/examples/Tutorial.cpp +215 -0
  101. data/examples/Tutorial.rb +137 -0
  102. data/examples/media/Beep.wav +0 -0
  103. data/examples/media/CptnRuby Gem.png +0 -0
  104. data/examples/media/CptnRuby Map.txt +25 -0
  105. data/examples/media/CptnRuby Tileset.png +0 -0
  106. data/examples/media/CptnRuby.png +0 -0
  107. data/examples/media/Cursor.png +0 -0
  108. data/examples/media/Earth.png +0 -0
  109. data/examples/media/Explosion.wav +0 -0
  110. data/examples/media/LargeStar.png +0 -0
  111. data/examples/media/Sky.jpg +0 -0
  112. data/examples/media/Smoke.png +0 -0
  113. data/examples/media/Soldier.png +0 -0
  114. data/examples/media/Space.png +0 -0
  115. data/examples/media/Star.png +0 -0
  116. data/examples/media/Starfighter.bmp +0 -0
  117. data/linux/Makefile.in +98 -0
  118. data/linux/configure +5658 -0
  119. data/linux/configure.ac +126 -0
  120. data/linux/extconf.rb +11 -0
  121. data/mac/English.lproj/InfoPlist.strings +0 -0
  122. data/mac/Gosu-Info.plist +26 -0
  123. data/mac/Gosu.xcodeproj/project.pbxproj +1194 -0
  124. data/mac/RubyGosu Template-Info.plist +26 -0
  125. data/mac/libboost_thread_1_34_1_universal.a +0 -0
  126. data/mac/libboost_thread_d_1_34_1_universal.a +0 -0
  127. data/mac/libfmod_universal.a +0 -0
  128. data/mac/libpng_universal.a +0 -0
  129. data/mac/libz_universal.a +0 -0
  130. data/reference/Async_8hpp-source.html +70 -0
  131. data/reference/Audio_8hpp-source.html +114 -0
  132. data/reference/Audio_8hpp.html +50 -0
  133. data/reference/AutoLink_8hpp-source.html +38 -0
  134. data/reference/AutoLink_8hpp.html +34 -0
  135. data/reference/Bitmap_8hpp-source.html +85 -0
  136. data/reference/Bitmap_8hpp.html +58 -0
  137. data/reference/ButtonsMac_8hpp-source.html +133 -0
  138. data/reference/ButtonsWin_8hpp-source.html +133 -0
  139. data/reference/ButtonsX_8hpp-source.html +134 -0
  140. data/reference/Color_8hpp-source.html +169 -0
  141. data/reference/Color_8hpp.html +85 -0
  142. data/reference/Directories_8hpp-source.html +42 -0
  143. data/reference/Directories_8hpp.html +46 -0
  144. data/reference/Font_8hpp-source.html +65 -0
  145. data/reference/Font_8hpp.html +41 -0
  146. data/reference/Fwd_8hpp-source.html +52 -0
  147. data/reference/Fwd_8hpp.html +37 -0
  148. data/reference/Gosu_8hpp-source.html +48 -0
  149. data/reference/Gosu_8hpp.html +34 -0
  150. data/reference/GraphicsBase_8hpp-source.html +57 -0
  151. data/reference/GraphicsBase_8hpp.html +56 -0
  152. data/reference/Graphics_8hpp-source.html +96 -0
  153. data/reference/Graphics_8hpp.html +53 -0
  154. data/reference/IO_8hpp-source.html +255 -0
  155. data/reference/IO_8hpp.html +74 -0
  156. data/reference/ImageData_8hpp-source.html +62 -0
  157. data/reference/ImageData_8hpp.html +43 -0
  158. data/reference/Image_8hpp-source.html +126 -0
  159. data/reference/Image_8hpp.html +48 -0
  160. data/reference/Input_8hpp-source.html +118 -0
  161. data/reference/Input_8hpp.html +50 -0
  162. data/reference/Math_8hpp-source.html +92 -0
  163. data/reference/Math_8hpp.html +74 -0
  164. data/reference/Platform_8hpp-source.html +83 -0
  165. data/reference/Platform_8hpp.html +73 -0
  166. data/reference/RotFlip_8hpp-source.html +138 -0
  167. data/reference/RotFlip_8hpp.html +77 -0
  168. data/reference/Sockets_8hpp-source.html +130 -0
  169. data/reference/Sockets_8hpp.html +66 -0
  170. data/reference/TextInput_8hpp-source.html +64 -0
  171. data/reference/TextInput_8hpp.html +41 -0
  172. data/reference/Text_8hpp-source.html +51 -0
  173. data/reference/Text_8hpp.html +46 -0
  174. data/reference/Timing_8hpp-source.html +36 -0
  175. data/reference/Timing_8hpp.html +42 -0
  176. data/reference/Utility_8hpp-source.html +44 -0
  177. data/reference/Utility_8hpp.html +48 -0
  178. data/reference/WinUtility_8hpp-source.html +79 -0
  179. data/reference/WinUtility_8hpp.html +64 -0
  180. data/reference/Window_8hpp-source.html +91 -0
  181. data/reference/Window_8hpp.html +41 -0
  182. data/reference/annotated.html +51 -0
  183. data/reference/classGosu_1_1Audio-members.html +34 -0
  184. data/reference/classGosu_1_1Audio.html +46 -0
  185. data/reference/classGosu_1_1Bitmap-members.html +44 -0
  186. data/reference/classGosu_1_1Bitmap.html +263 -0
  187. data/reference/classGosu_1_1Buffer-members.html +44 -0
  188. data/reference/classGosu_1_1Buffer.html +78 -0
  189. data/reference/classGosu_1_1Buffer.png +0 -0
  190. data/reference/classGosu_1_1Button-members.html +36 -0
  191. data/reference/classGosu_1_1Button.html +143 -0
  192. data/reference/classGosu_1_1Color-members.html +56 -0
  193. data/reference/classGosu_1_1Color.html +387 -0
  194. data/reference/classGosu_1_1File-members.html +41 -0
  195. data/reference/classGosu_1_1File.html +69 -0
  196. data/reference/classGosu_1_1File.png +0 -0
  197. data/reference/classGosu_1_1Font-members.html +39 -0
  198. data/reference/classGosu_1_1Font.html +309 -0
  199. data/reference/classGosu_1_1Graphics-members.html +50 -0
  200. data/reference/classGosu_1_1Graphics.html +234 -0
  201. data/reference/classGosu_1_1Image-members.html +45 -0
  202. data/reference/classGosu_1_1Image.html +518 -0
  203. data/reference/classGosu_1_1ImageData-members.html +37 -0
  204. data/reference/classGosu_1_1ImageData.html +60 -0
  205. data/reference/classGosu_1_1Input-members.html +44 -0
  206. data/reference/classGosu_1_1Input.html +223 -0
  207. data/reference/classGosu_1_1MessageSocket-members.html +40 -0
  208. data/reference/classGosu_1_1MessageSocket.html +233 -0
  209. data/reference/classGosu_1_1Resource-members.html +39 -0
  210. data/reference/classGosu_1_1Resource.html +116 -0
  211. data/reference/classGosu_1_1Resource.png +0 -0
  212. data/reference/classGosu_1_1Sample-members.html +37 -0
  213. data/reference/classGosu_1_1Sample.html +200 -0
  214. data/reference/classGosu_1_1SampleInstance-members.html +38 -0
  215. data/reference/classGosu_1_1SampleInstance.html +169 -0
  216. data/reference/classGosu_1_1Song-members.html +43 -0
  217. data/reference/classGosu_1_1Song.html +260 -0
  218. data/reference/classGosu_1_1TextInput-members.html +38 -0
  219. data/reference/classGosu_1_1TextInput.html +121 -0
  220. data/reference/classGosu_1_1Window-members.html +50 -0
  221. data/reference/classGosu_1_1Window.html +271 -0
  222. data/reference/doxyfile +233 -0
  223. data/reference/doxygen.css +433 -0
  224. data/reference/doxygen.png +0 -0
  225. data/reference/files.html +54 -0
  226. data/reference/functions.html +236 -0
  227. data/reference/functions_enum.html +45 -0
  228. data/reference/functions_func.html +227 -0
  229. data/reference/functions_vars.html +47 -0
  230. data/reference/hierarchy.html +53 -0
  231. data/reference/index.html +26 -0
  232. data/reference/namespaceGosu.html +2890 -0
  233. data/reference/namespaceGosu_1_1Colors.html +70 -0
  234. data/reference/namespaceGosu_1_1Win.html +275 -0
  235. data/reference/namespacemembers.html +216 -0
  236. data/reference/namespacemembers_enum.html +52 -0
  237. data/reference/namespacemembers_eval.html +54 -0
  238. data/reference/namespacemembers_func.html +185 -0
  239. data/reference/namespacemembers_type.html +46 -0
  240. data/reference/namespacemembers_vars.html +46 -0
  241. data/reference/namespaces.html +35 -0
  242. data/reference/tab_b.gif +0 -0
  243. data/reference/tab_l.gif +0 -0
  244. data/reference/tab_r.gif +0 -0
  245. data/reference/tabs.css +102 -0
  246. data/windows/Gosu.sln +29 -0
  247. data/windows/Gosu.vcproj +553 -0
  248. data/windows/RubyGosu.vcproj +138 -0
  249. metadata +305 -0
@@ -0,0 +1,145 @@
1
+ #include <Gosu/Sockets.hpp>
2
+ #include <GosuImpl/Sockets/Sockets.hpp>
3
+ #ifdef GOSU_IS_WIN
4
+ #include <Gosu/WinUtility.hpp>
5
+ #endif
6
+ #include <cstdlib>
7
+ #include <cstring>
8
+ #include <algorithm>
9
+ #include <stdexcept>
10
+
11
+ namespace Gosu
12
+ {
13
+ namespace
14
+ {
15
+ void cleanup()
16
+ {
17
+ #ifdef GOSU_IS_WIN
18
+ ::WSACleanup();
19
+ #endif
20
+ }
21
+
22
+ void needsSockLib()
23
+ {
24
+ #ifdef GOSU_IS_WIN
25
+ static bool initialized = false;
26
+ if (!initialized)
27
+ {
28
+ WSADATA data;
29
+ if (::WSAStartup(0x0202, &data) != 0)
30
+ throw std::runtime_error("Could not initialize "
31
+ "Windows sockets");
32
+
33
+ initialized = true;
34
+ std::atexit(cleanup);
35
+ }
36
+ #endif
37
+ }
38
+ }
39
+ }
40
+
41
+ int Gosu::lastSocketError()
42
+ {
43
+ #ifdef GOSU_IS_WIN
44
+ needsSockLib();
45
+ return ::WSAGetLastError();
46
+ #else
47
+ return errno;
48
+ #endif
49
+ }
50
+
51
+ GOSU_NORETURN void Gosu::throwLastSocketError()
52
+ {
53
+ #ifdef GOSU_IS_WIN
54
+ Win::throwLastError();
55
+ #else
56
+ throw std::runtime_error(strerror(errno));
57
+ #endif
58
+ }
59
+
60
+ Gosu::SocketAddress Gosu::stringToAddress(const std::string& s)
61
+ {
62
+ needsSockLib();
63
+
64
+ SocketAddress address;
65
+
66
+ // Try to interpret name as an IP number string.
67
+ address = ntohl(::inet_addr(s.c_str()));
68
+ if (address != INADDR_NONE)
69
+ return address;
70
+
71
+ // This didn't work: Resolve host name via DNS.
72
+ hostent* host = ::gethostbyname(s.c_str());
73
+ if (!host)
74
+ return 0;
75
+ in_addr addr = *reinterpret_cast<in_addr*>(host->h_addr_list[0]);
76
+ return ntohl(addr.s_addr);
77
+ }
78
+
79
+ std::string Gosu::addressToString(SocketAddress address)
80
+ {
81
+ needsSockLib();
82
+
83
+ in_addr addr;
84
+ addr.s_addr = htonl(address);
85
+ return ::inet_ntoa(addr);
86
+ }
87
+
88
+ Gosu::Socket::Socket()
89
+ : handle_(INVALID_SOCKET)
90
+ {
91
+ needsSockLib();
92
+ }
93
+
94
+ Gosu::Socket::~Socket()
95
+ {
96
+ setHandle(INVALID_SOCKET);
97
+ }
98
+
99
+ Gosu::SocketHandle Gosu::Socket::handle() const
100
+ {
101
+ return handle_;
102
+ }
103
+
104
+ void Gosu::Socket::setHandle(SocketHandle value)
105
+ {
106
+ if (handle() != INVALID_SOCKET)
107
+ {
108
+ ::closesocket(handle());
109
+ }
110
+
111
+ handle_ = value;
112
+ }
113
+
114
+ void Gosu::Socket::setBlocking(bool value)
115
+ {
116
+ u_long enable = !value;
117
+ socketCheck(::ioctlsocket(handle(), FIONBIO, &enable));
118
+ }
119
+
120
+ Gosu::SocketAddress Gosu::Socket::address() const
121
+ {
122
+ sockaddr_in addr;
123
+ int size = sizeof addr;
124
+ socketCheck(::getsockname(handle(),
125
+ reinterpret_cast<sockaddr*>(&addr),
126
+ reinterpret_cast<socklen_t*>(&size)));
127
+
128
+ return ntohl(addr.sin_addr.s_addr);
129
+ }
130
+
131
+ Gosu::SocketPort Gosu::Socket::port() const
132
+ {
133
+ sockaddr_in addr;
134
+ int size = sizeof addr;
135
+ socketCheck(::getsockname(handle(),
136
+ reinterpret_cast<sockaddr*>(&addr),
137
+ reinterpret_cast<socklen_t*>(&size)));
138
+
139
+ return ntohs(addr.sin_port);
140
+ }
141
+
142
+ void Gosu::Socket::swap(Socket& other)
143
+ {
144
+ std::swap(handle_, other.handle_);
145
+ }
@@ -0,0 +1,66 @@
1
+ #ifndef GOSUIMPL_SOCKETS_HPP
2
+ #define GOSUIMPL_SOCKETS_HPP
3
+
4
+ #include <Gosu/Platform.hpp>
5
+ #include <boost/utility.hpp>
6
+
7
+ #ifdef GOSU_IS_WIN
8
+ #include "winsock2.h"
9
+ #define GOSU_SOCK_ERR(code) WSA##code
10
+ namespace Gosu { typedef SOCKET SocketHandle; }
11
+ typedef int socklen_t;
12
+ #else
13
+ #include <sys/errno.h>
14
+ #include <sys/socket.h>
15
+ #include <netinet/in.h>
16
+ #include <arpa/inet.h>
17
+ #include <netdb.h>
18
+ #include <sys/ioctl.h>
19
+ #define GOSU_SOCK_ERR(code) code
20
+ // IMPR: Macros ok?
21
+ #define INVALID_SOCKET -1
22
+ #define SOCKET_ERROR -1
23
+ #define closesocket close
24
+ #define ioctlsocket ioctl
25
+ namespace Gosu { typedef int SocketHandle; }
26
+ #endif
27
+
28
+ namespace Gosu
29
+ {
30
+ // Owns a socket and manages library initialization.
31
+ class Socket : boost::noncopyable
32
+ {
33
+ SocketHandle handle_;
34
+
35
+ public:
36
+ Socket();
37
+ ~Socket();
38
+
39
+ SocketHandle handle() const;
40
+ void setHandle(SocketHandle value);
41
+ void setBlocking(bool value);
42
+
43
+ SocketAddress address() const;
44
+ SocketPort port() const;
45
+
46
+ void swap(Socket& other);
47
+ };
48
+
49
+ int lastSocketError();
50
+
51
+ GOSU_NORETURN void throwLastSocketError();
52
+
53
+ template<typename T>
54
+ T socketCheck(T retVal)
55
+ {
56
+ if (retVal == SOCKET_ERROR &&
57
+ lastSocketError() != GOSU_SOCK_ERR(EWOULDBLOCK))
58
+ {
59
+ throwLastSocketError();
60
+ }
61
+
62
+ return retVal;
63
+ }
64
+ }
65
+
66
+ #endif
@@ -0,0 +1,207 @@
1
+ #include <Gosu/TextInput.hpp>
2
+ #include <Gosu/ButtonsMac.hpp>
3
+ #include <GosuImpl/MacUtility.hpp>
4
+ #include <algorithm>
5
+ #include <vector>
6
+ #include <wctype.h>
7
+
8
+ #import <Cocoa/Cocoa.h>
9
+
10
+ // Sometimes macro DSLs aren't evil.
11
+ #define CARET_POS (*_caretPos)
12
+ #define SEL_START (*_selectionStart)
13
+ #define IMPL_WITH_SEL_RESET(selector) \
14
+ - (void)selector:(id)sender \
15
+ { \
16
+ [self selector##AndModifySelection:sender]; \
17
+ SEL_START = CARET_POS; \
18
+ }
19
+
20
+ @interface GosuTextInput : NSResponder
21
+ {
22
+ std::wstring* _text;
23
+ unsigned* _caretPos;
24
+ unsigned* _selectionStart;
25
+ }
26
+ @end
27
+ @implementation GosuTextInput
28
+ - (void)insertText:(id)insertString
29
+ {
30
+ // Delete (overwrite) previous selection.
31
+ if (CARET_POS != SEL_START)
32
+ {
33
+ unsigned min = std::min(CARET_POS, SEL_START);
34
+ unsigned max = std::max(CARET_POS, SEL_START);
35
+ _text->erase(_text->begin() + min, _text->begin() + max);
36
+ CARET_POS = SEL_START = min;
37
+ }
38
+
39
+ NSString* str = (NSString*)insertString;
40
+
41
+ if ([str length] == 0)
42
+ return;
43
+
44
+ std::vector<unichar> unibuf([str length]);
45
+ [str getCharacters: &unibuf[0]];
46
+
47
+ _text->insert(_text->begin() + CARET_POS, unibuf.begin(), unibuf.end());
48
+ (CARET_POS) += unibuf.size();
49
+ (SEL_START) = CARET_POS;
50
+ }
51
+
52
+ // Movement.
53
+
54
+ - (void)moveLeftAndModifySelection:(id)sender
55
+ {
56
+ if (CARET_POS > 0)
57
+ (CARET_POS) -= 1;
58
+ }
59
+ - (void)moveRightAndModifySelection:(id)sender
60
+ {
61
+ if (CARET_POS < _text->length())
62
+ (CARET_POS) += 1;
63
+ }
64
+ - (void)moveUpAndModifySelection:(id)sender
65
+ {
66
+ CARET_POS = 0;
67
+ }
68
+ - (void)moveDownAndModifySelection:(id)sender
69
+ {
70
+ CARET_POS = _text->length();
71
+ }
72
+ - (void)moveToBeginningOfLineAndModifySelection:(id)sender
73
+ {
74
+ [self moveUpAndModifySelection: sender];
75
+ }
76
+ - (void)moveToEndOfLineAndModifySelection:(id)sender
77
+ {
78
+ [self moveDownAndModifySelection: sender];
79
+ }
80
+ - (void)moveToBeginningOfDocumentAndModifySelection:(id)sender
81
+ {
82
+ [self moveUpAndModifySelection: sender];
83
+ }
84
+ - (void)moveToEndOfDocumentAndModifySelection:(id)sender
85
+ {
86
+ [self moveDownAndModifySelection: sender];
87
+ }
88
+ - (void)moveWordLeftAndModifySelection:(id)sender
89
+ {
90
+ if (CARET_POS == _text->length())
91
+ --CARET_POS;
92
+
93
+ while (CARET_POS > 0 && iswspace(_text->at(CARET_POS - 1)))
94
+ --CARET_POS;
95
+
96
+ while (CARET_POS > 0 && !iswspace(_text->at(CARET_POS - 1)))
97
+ --CARET_POS;
98
+ }
99
+ - (void)moveWordRightAndModifySelection:(id)sender
100
+ {
101
+ while (CARET_POS < _text->length() && iswspace(_text->at(CARET_POS)))
102
+ ++CARET_POS;
103
+
104
+ while (CARET_POS < _text->length() && !iswspace(_text->at(CARET_POS)))
105
+ ++CARET_POS;
106
+ }
107
+
108
+ IMPL_WITH_SEL_RESET(moveLeft)
109
+ IMPL_WITH_SEL_RESET(moveRight)
110
+ IMPL_WITH_SEL_RESET(moveUp)
111
+ IMPL_WITH_SEL_RESET(moveDown)
112
+ IMPL_WITH_SEL_RESET(moveWordLeft)
113
+ IMPL_WITH_SEL_RESET(moveWordRight)
114
+ IMPL_WITH_SEL_RESET(moveToBeginningOfLine)
115
+ IMPL_WITH_SEL_RESET(moveToEndOfLine)
116
+ IMPL_WITH_SEL_RESET(moveToBeginningOfDocument)
117
+ IMPL_WITH_SEL_RESET(moveToEndOfDocument)
118
+
119
+ // Deletion.
120
+
121
+ - (void)deleteBackward:(id)sender
122
+ {
123
+ if (CARET_POS == SEL_START && CARET_POS > 0)
124
+ --CARET_POS;
125
+ [self insertText: @""];
126
+ }
127
+ - (void)deleteForward:(id)sender
128
+ {
129
+ if (CARET_POS == SEL_START && CARET_POS < _text->length())
130
+ ++CARET_POS;
131
+ [self insertText: @""];
132
+ }
133
+
134
+ // TODO: Advanced deletion (deleteWord...)
135
+
136
+ // Selection.
137
+
138
+ - (void)selectAll:(id)sender
139
+ {
140
+ SEL_START = 0;
141
+ CARET_POS = _text->length();
142
+ }
143
+
144
+ // TODO: Cmd+A should really be hard-coded into selectAll.
145
+
146
+ // Helper to set up this instance.
147
+
148
+ - (void)setText:(std::wstring&)text andCaretPos:(unsigned&)caretPos andSelectionStart:(unsigned&)selectionStart
149
+ {
150
+ _text = &text;
151
+ _caretPos = &caretPos;
152
+ _selectionStart = &selectionStart;
153
+ }
154
+ @end
155
+
156
+ struct Gosu::TextInput::Impl
157
+ {
158
+ ObjRef<GosuTextInput> responder;
159
+ std::wstring text;
160
+ unsigned caretPos, selectionStart;
161
+ Impl() : caretPos(0), selectionStart(0) {}
162
+ };
163
+
164
+ Gosu::TextInput::TextInput()
165
+ : pimpl(new Impl)
166
+ {
167
+ pimpl->responder.reset([[GosuTextInput alloc] init]);
168
+ [pimpl->responder.get() setText: pimpl->text andCaretPos: pimpl->caretPos andSelectionStart: pimpl->selectionStart];
169
+ }
170
+
171
+ Gosu::TextInput::~TextInput()
172
+ {
173
+ }
174
+
175
+ std::wstring Gosu::TextInput::text() const
176
+ {
177
+ return pimpl->text;
178
+ }
179
+
180
+ void Gosu::TextInput::setText(const std::wstring& text)
181
+ {
182
+ pimpl->text = text;
183
+ pimpl->caretPos = pimpl->selectionStart = text.length();
184
+ }
185
+
186
+ unsigned Gosu::TextInput::caretPos() const
187
+ {
188
+ return pimpl->caretPos;
189
+ }
190
+
191
+ unsigned Gosu::TextInput::selectionStart() const
192
+ {
193
+ return pimpl->selectionStart;
194
+ }
195
+
196
+ bool Gosu::TextInput::feedNSEvent(void* event)
197
+ {
198
+ NSEvent* nsEvent = (NSEvent*)event;
199
+ long keyCode = [nsEvent keyCode];
200
+ if (keyCode != kbEscape && keyCode != kbTab && keyCode != kbReturn && keyCode != kbEnter)
201
+ {
202
+ [pimpl->responder.get() interpretKeyEvents: [NSArray arrayWithObject: nsEvent]];
203
+ return true;
204
+ }
205
+ else
206
+ return false;
207
+ }
@@ -0,0 +1,197 @@
1
+ #include <Gosu/TextInput.hpp>
2
+ #include <Gosu/ButtonsWin.hpp>
3
+ #include <algorithm>
4
+ #include <vector>
5
+ #include <wctype.h>
6
+
7
+ // OPT-IN, have you heard of it?!
8
+ #define NOMINMAX
9
+ #include <windows.h>
10
+
11
+ struct Gosu::TextInput::Impl
12
+ {
13
+ std::wstring text;
14
+ unsigned caretPos, selectionStart;
15
+ Impl() : caretPos(0), selectionStart(0) {}
16
+ };
17
+
18
+ Gosu::TextInput::TextInput()
19
+ : pimpl(new Impl)
20
+ {
21
+ }
22
+
23
+ Gosu::TextInput::~TextInput()
24
+ {
25
+ }
26
+
27
+ std::wstring Gosu::TextInput::text() const
28
+ {
29
+ return pimpl->text;
30
+ }
31
+
32
+ void Gosu::TextInput::setText(const std::wstring& text)
33
+ {
34
+ pimpl->text = text;
35
+ pimpl->caretPos = pimpl->selectionStart = text.length();
36
+ }
37
+
38
+ unsigned Gosu::TextInput::caretPos() const
39
+ {
40
+ return pimpl->caretPos;
41
+ }
42
+
43
+ unsigned Gosu::TextInput::selectionStart() const
44
+ {
45
+ return pimpl->selectionStart;
46
+ }
47
+
48
+ #define CARET_POS (pimpl->caretPos)
49
+ #define SEL_START (pimpl->selectionStart)
50
+
51
+ bool Gosu::TextInput::feedMessage(unsigned long message, unsigned long wparam, unsigned long lparam)
52
+ {
53
+ if (message == WM_CHAR && wparam >= 32 && wparam != 127)
54
+ {
55
+ // Delete (overwrite) previous selection.
56
+ if (CARET_POS != SEL_START)
57
+ {
58
+ unsigned min = std::min(CARET_POS, SEL_START);
59
+ unsigned max = std::max(CARET_POS, SEL_START);
60
+ pimpl->text.erase(pimpl->text.begin() + min, pimpl->text.begin() + max);
61
+ CARET_POS = SEL_START = min;
62
+ }
63
+
64
+ pimpl->text.insert(pimpl->text.begin() + CARET_POS, static_cast<wchar_t>(wparam));
65
+ CARET_POS += 1;
66
+ SEL_START = CARET_POS;
67
+ return true;
68
+ }
69
+
70
+ bool ctrlDown = (GetKeyState(VK_CONTROL) < 0);
71
+ bool shiftDown = (GetKeyState(VK_SHIFT) < 0);
72
+
73
+ // Char left
74
+ if (message == WM_KEYDOWN && wparam == VK_LEFT && !ctrlDown)
75
+ {
76
+ if (CARET_POS > 0)
77
+ CARET_POS -= 1;
78
+
79
+ if (!shiftDown)
80
+ SEL_START = CARET_POS;
81
+
82
+ return true;
83
+ }
84
+
85
+ // Char right
86
+ if (message == WM_KEYDOWN && wparam == VK_RIGHT && !ctrlDown)
87
+ {
88
+ if (CARET_POS < pimpl->text.length())
89
+ CARET_POS += 1;
90
+
91
+ if (!shiftDown)
92
+ SEL_START = CARET_POS;
93
+
94
+ return true;
95
+ }
96
+
97
+ // Home
98
+ if (message == WM_KEYDOWN && wparam == VK_HOME)
99
+ {
100
+ CARET_POS = 0;
101
+
102
+ if (!shiftDown)
103
+ SEL_START = CARET_POS;
104
+
105
+ return true;
106
+ }
107
+
108
+ // End
109
+ if (message == WM_KEYDOWN && wparam == VK_END)
110
+ {
111
+ CARET_POS = pimpl->text.length();
112
+
113
+ if (!shiftDown)
114
+ SEL_START = CARET_POS;
115
+
116
+ return true;
117
+ }
118
+
119
+ // Word left
120
+ if (message == WM_KEYDOWN && wparam == VK_LEFT && ctrlDown)
121
+ {
122
+ if (CARET_POS == pimpl->text.length())
123
+ --CARET_POS;
124
+
125
+ while (CARET_POS > 0 && iswspace(pimpl->text.at(CARET_POS - 1)))
126
+ --CARET_POS;
127
+
128
+ while (CARET_POS > 0 && !iswspace(pimpl->text.at(CARET_POS - 1)))
129
+ --CARET_POS;
130
+
131
+ if (!shiftDown)
132
+ SEL_START = CARET_POS;
133
+
134
+ return true;
135
+ }
136
+
137
+ // Word right
138
+ if (message == WM_KEYDOWN && wparam == VK_RIGHT && ctrlDown)
139
+ {
140
+ while (CARET_POS < pimpl->text.length() && iswspace(pimpl->text.at(CARET_POS)))
141
+ ++CARET_POS;
142
+
143
+ while (CARET_POS < pimpl->text.length() && !iswspace(pimpl->text.at(CARET_POS)))
144
+ ++CARET_POS;
145
+
146
+ if (!shiftDown)
147
+ SEL_START = CARET_POS;
148
+
149
+ return true;
150
+ }
151
+
152
+ // Delete existant selection
153
+ if (message == WM_KEYDOWN && wparam == VK_BACK)
154
+ {
155
+ if (SEL_START != CARET_POS)
156
+ {
157
+ unsigned min = std::min(CARET_POS, SEL_START);
158
+ unsigned max = std::max(CARET_POS, SEL_START);
159
+ pimpl->text.erase(pimpl->text.begin() + min, pimpl->text.begin() + max);
160
+ SEL_START = CARET_POS = min;
161
+ }
162
+ else
163
+ {
164
+ unsigned oldCaret = CARET_POS;
165
+ // Move left - either char or word
166
+ feedMessage(WM_KEYDOWN, VK_LEFT, lparam);
167
+ pimpl->text.erase(pimpl->text.begin() + CARET_POS, pimpl->text.begin() + oldCaret);
168
+ SEL_START = CARET_POS;
169
+ }
170
+
171
+ return true;
172
+ }
173
+
174
+ // Delete existant selection
175
+ if (message == WM_KEYDOWN && wparam == VK_DELETE)
176
+ {
177
+ if (SEL_START != CARET_POS)
178
+ {
179
+ unsigned min = std::min(CARET_POS, SEL_START);
180
+ unsigned max = std::max(CARET_POS, SEL_START);
181
+ pimpl->text.erase(pimpl->text.begin() + min, pimpl->text.begin() + max);
182
+ SEL_START = CARET_POS = min;
183
+ }
184
+ else
185
+ {
186
+ unsigned oldCaret = CARET_POS;
187
+ // Move right - either char or word
188
+ feedMessage(WM_KEYDOWN, VK_RIGHT, lparam);
189
+ pimpl->text.erase(pimpl->text.begin() + oldCaret, pimpl->text.begin() + CARET_POS);
190
+ SEL_START = CARET_POS = oldCaret;
191
+ }
192
+
193
+ return true;
194
+ }
195
+
196
+ return false;
197
+ }