Commit 1f8dacab authored by Sam Lantinga's avatar Sam Lantinga

Merged Daniel's Google Summer of Code work from SDL-gsoc2010_IME

parents 66d40ad3 7d245d05

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GLIMM", "GLIMM.vcproj", "{F21B830F-20A9-4473-B67A-21D1743C6E19}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F21B830F-20A9-4473-B67A-21D1743C6E19}.Debug|Win32.ActiveCfg = Debug|Win32
{F21B830F-20A9-4473-B67A-21D1743C6E19}.Debug|Win32.Build.0 = Debug|Win32
{F21B830F-20A9-4473-B67A-21D1743C6E19}.Release|Win32.ActiveCfg = Release|Win32
{F21B830F-20A9-4473-B67A-21D1743C6E19}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="GLIMM"
ProjectGUID="{F21B830F-20A9-4473-B67A-21D1743C6E19}"
RootNamespace="GLIMM"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)bin"
IntermediateDirectory="obj\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="imm32.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)bin"
IntermediateDirectory="obj\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="imm32.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\src\App.cpp"
>
</File>
<File
RelativePath=".\src\IMM.cpp"
>
</File>
<File
RelativePath=".\src\Main.cpp"
>
</File>
<File
RelativePath=".\src\Video_Mode.cpp"
>
</File>
<File
RelativePath=".\src\Window.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\include\App.hpp"
>
</File>
<File
RelativePath=".\include\IMM.hpp"
>
</File>
<File
RelativePath=".\include\Video_Mode.hpp"
>
</File>
<File
RelativePath=".\include\Window.hpp"
>
</File>
<File
RelativePath=".\include\Window_Listener.hpp"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
#ifndef APP_HPP
#define APP_HPP
#include "Window.hpp"
class App : public Window_Listener
{
public:
App();
virtual ~App();
void Initialize();
void Finalize();
void Run();
virtual void On_Close();
virtual void On_Key_Down(int Key);
virtual void On_Key_Up(int Key);
virtual void On_Char(unsigned int Char);
virtual void On_Resized(unsigned int Width, unsigned int Height);
virtual void On_Mouse_Button_Down(Mouse_Button Button);
private:
void Update();
void Draw();
static const int Width = 800;
static const int Height = 600;
static const int Bits_Per_Pixel = 32;
static const bool Fullscreen = true;
Window my_Window;
bool my_Done;
};
#endif
#ifndef IMM_HPP
#define IMM_HPP
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <msctf.h>
class IMM
{
public:
IMM();
~IMM();
void Initialize(HWND Window);
void Finalize();
LRESULT Handle_Message(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam, bool &Ate);
void Enable();
void Disable();
bool Is_Enabled();
void Toggle();
void Focus_Gained();
void Focus_Lost();
private:
void Update_Input_Locale();
void Cancel_Composition();
void Input_Language_Changed();
bool my_COM_Initialized;
ITfThreadMgr *my_Thread_Manager;
HWND my_Window;
HIMC my_Context;
HKL my_HKL;
bool my_Vertical_Candidates;
bool my_Enabled;
};
#endif
#ifndef VIDEO_MODE_HPP
#define VIDEO_MODE_HPP
#include <cstddef>
class Video_Mode
{
public:
Video_Mode();
Video_Mode(unsigned int The_Width, unsigned int The_Height, unsigned int The_Bits_Per_Pixel);
static Video_Mode Get_Desktop_Mode();
static std::size_t Get_Mode_Count();
static Video_Mode Get_Mode(std::size_t Index);
bool Is_Valid() const;
bool operator==(const Video_Mode &Mode) const;
bool operator!=(const Video_Mode &Mode) const;
unsigned int Width;
unsigned int Height;
unsigned int Bits_Per_Pixel;
private:
static void Initialize_Modes();
};
#endif
#ifndef WINDOW_HPP
#define WINDOW_HPP
#include <string>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "Video_Mode.hpp"
#include "Window_Listener.hpp"
#include "IMM.hpp"
class Window
{
public:
Window();
~Window();
void Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen);
void Finalize();
void Set_Listener(Window_Listener *Listener);
void Show();
void Hide();
void Handle_Events();
void Display();
void Show_Cursor();
void Hide_Cursor();
HWND Get_Handle();
IMM &Get_IMM();
private:
static const wchar_t *Window_Class_Name;
void Register_Class();
void Unregister_Class();
void Create_Window(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen);
void Destroy_Window();
void Create_Context(const Video_Mode &Mode);
void Destroy_Context();
void Switch_To_Fullscreen(const Video_Mode &Mode);
LRESULT Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK Window_Procedure(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam);
HWND my_Handle;
Video_Mode my_Video_Mode;
bool my_Fullscreen;
HDC my_Device_Context;
HGLRC my_GL_Context;
bool my_Class_Registered;
Window_Listener *my_Listener;
IMM my_IMM;
};
#endif
#ifndef WINDOW_LISTENER_HPP
#define WINDOW_LISTENER_HPP
enum Mouse_Button
{
Mouse_Button_Left,
Mouse_Button_Right
};
class Window_Listener
{
public:
virtual void On_Close(){}
virtual void On_Key_Down(int Key){}
virtual void On_Key_Up(int Key){}
virtual void On_Char(unsigned int Char){}
virtual void On_Resized(unsigned int Width, unsigned int Height){}
virtual void On_Mouse_Button_Down(Mouse_Button Button){}
virtual void On_Mouse_Button_Up(Mouse_Button Button){}
};
#endif
#include "App.hpp"
#include <GL/gl.h>
#include <GL/glu.h>
#pragma comment(lib, "glu32.lib")
GLfloat Rotation = 0.0f;
App::App() : my_Done(false)
{
}
App::~App()
{
Finalize();
}
void App::Initialize()
{
Finalize();
my_Window.Initialize(L"GLIMM", Video_Mode(Width, Height, Bits_Per_Pixel), Fullscreen);
my_Window.Set_Listener(this);
my_Window.Show();
my_Window.Hide_Cursor();
}
void App::Finalize()
{
my_Window.Finalize();
}
void App::Run()
{
Initialize();
while (!my_Done)
{
my_Window.Handle_Events();
Update();
Draw();
my_Window.Display();
}
}
void App::On_Close()
{
my_Done = true;
my_Window.Hide();
}
void App::On_Key_Down(int Key)
{
switch (Key)
{
case VK_ESCAPE:
On_Close();
break;
}
}
void App::On_Key_Up(int Key)
{
}
void App::On_Char(unsigned int Char)
{
printf("Char: U+%04X\n", Char);
}
void App::On_Resized(unsigned int Width, unsigned int Height)
{
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void App::On_Mouse_Button_Down(Mouse_Button Button)
{
switch (Button)
{
case Mouse_Button_Left:
my_Window.Get_IMM().Toggle();
break;
}
}
void App::Update()
{
Rotation += 0.2f;
}
void App::Draw()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glRotatef(Rotation, 0.0f, 0.0f, -1.0f);
glBegin(GL_TRIANGLES);
glColor3f(0.7f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
glColor3f(0.0f, 0.7f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.0f);
glColor3f(0.0f, 0.0f, 0.7f);
glVertex3f(0.5f, -0.5f, 0.0f);
glEnd();
}
#include "IMM.hpp"
#include <stdexcept>
IMM::IMM() : my_COM_Initialized(false),
my_Thread_Manager(0),
my_Window(0),
my_Context(0),
my_HKL(0),
my_Vertical_Candidates(false),
my_Enabled(false)
{
}
IMM::~IMM()
{
Finalize();
}
void IMM::Initialize(HWND Window)
{
Finalize();
my_Window = Window;
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
{
my_COM_Initialized = true;
if (SUCCEEDED(CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfThreadMgr, reinterpret_cast<LPVOID *>(&my_Thread_Manager))))
{
ITfDocumentMgr *Document_Manager = 0;
if (SUCCEEDED(my_Thread_Manager->AssociateFocus(Window, NULL, &Document_Manager)))
{
if (Document_Manager)
Document_Manager->Release();
}
else
printf("Warning: ITfThreadMgr->AssociateFocus failed\n");
}
else
printf("Warning: Failed to create ITfThreadMgr instance\n");
}
else
printf("Warning: Failed to initialize COM\n");
ImmDisableTextFrameService((DWORD)-1);
my_Context = ImmGetContext(my_Window);
ImmReleaseContext(my_Window, my_Context);
if (!my_Context)
throw std::runtime_error("No context (No IME installed?)");
Update_Input_Locale();
Cancel_Composition();
Disable();
}
void IMM::Finalize()
{
if (my_Thread_Manager)
{
my_Thread_Manager->Release();
my_Thread_Manager = 0;
}
if (my_COM_Initialized)
{
CoUninitialize();
my_COM_Initialized = false;
}
}
#define GET_LANG(hkl) LOWORD((hkl))
#define GET_PRIMLANG(hkl) ((WORD)PRIMARYLANGID(GET_LANG((hkl))))
#define GET_SUBLANG(hkl) SUBLANGID(GET_LANG((hkl)))
void IMM::Update_Input_Locale()
{
static HKL Previous_HKL = 0;
my_HKL = GetKeyboardLayout(0);
if (Previous_HKL == my_HKL)
return;
Previous_HKL = my_HKL;
my_Vertical_Candidates = false;
switch (GET_PRIMLANG(my_HKL))
{
case LANG_CHINESE:
my_Vertical_Candidates = true;
switch (GET_SUBLANG(my_HKL))
{
case SUBLANG_CHINESE_SIMPLIFIED:
my_Vertical_Candidates = false;
break;
}
break;
case LANG_JAPANESE:
my_Vertical_Candidates = true;
break;
}
}
LRESULT IMM::Handle_Message(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam, bool &Ate)
{
Ate = false;
switch (Message)
{
case WM_INPUTLANGCHANGE:
Input_Language_Changed();
break;
case WM_IME_SETCONTEXT:
lParam = 0;
break;
case WM_IME_STARTCOMPOSITION:
Ate = true;
break;
case WM_IME_COMPOSITION:
{
Ate = true;
HIMC Context = ImmGetContext(Window);
if (!Context)
break;
if (lParam & GCS_RESULTSTR)
{
LONG Length = ImmGetCompositionStringW(Context, GCS_RESULTSTR, 0, 0);
std::wstring Composition(Length / sizeof(wchar_t), 0);
Length = ImmGetCompositionStringW(Context, GCS_RESULTSTR, &Composition[0], Composition.size() * sizeof(Composition[0]));
printf("GCS_RESULTSTR: ");
for (LONG i = 0; i < Length / sizeof(wchar_t); ++i)
printf("U+%04X ", Composition[i]);
printf("\n");
}
if (lParam & GCS_COMPSTR)
{
LONG Length = ImmGetCompositionStringW(Context, GCS_COMPSTR, 0, 0);
std::wstring Composition(Length / sizeof(wchar_t), 0);
Length = ImmGetCompositionStringW(Context, GCS_COMPSTR, &Composition[0], Composition.size() * sizeof(Composition[0]));
printf("GCS_COMPSTR: ");
for (LONG i = 0; i < Length / sizeof(wchar_t); ++i)
printf("U+%04X ", Composition[i]);
printf("\n");
}
ImmReleaseContext(Window, Context);
}
break;
case WM_IME_ENDCOMPOSITION:
break;
case WM_IME_NOTIFY:
switch (wParam)
{
case IMN_SETCONVERSIONMODE:
break;
case IMN_SETOPENSTATUS:
Update_Input_Locale();
break;
case IMN_OPENCANDIDATE:
case IMN_CHANGECANDIDATE:
Ate = true;
break;
case IMN_CLOSECANDIDATE:
Ate = true;
break;
default:
Ate = true;
break;
}
break;
}
return 0;
}
void IMM::Enable()
{
ImmAssociateContext(my_Window, my_Context);
Update_Input_Locale();
my_Enabled = true;
printf("* Enabled\n");
}
void IMM::Disable()
{
ImmAssociateContext(my_Window, 0);
my_Enabled = false;
printf("* Disabled\n");
}
bool IMM::Is_Enabled()
{
return my_Enabled;
}
void IMM::Toggle()
{
if (my_Enabled)
Disable();
else
Enable();
}
void IMM::Focus_Gained()
{
if (my_Enabled)
Enable();
}
void IMM::Focus_Lost()
{
bool Enabled = my_Enabled;
Cancel_Composition();
Disable();
my_Enabled = Enabled;
}
void IMM::Cancel_Composition()
{
HIMC hIMC = ImmGetContext(my_Window);
if (!hIMC)
return;
ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
ImmNotifyIME(hIMC, NI_CLOSECANDIDATE, 0, 0);
ImmReleaseContext(my_Window, hIMC);
}
void IMM::Input_Language_Changed()
{
Update_Input_Locale();
HWND hwndImeDef = ImmGetDefaultIMEWnd(my_Window);
if (hwndImeDef)
{
SendMessageA(hwndImeDef, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0);
SendMessageA(hwndImeDef, WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0);
}
}
#include "App.hpp"
#include <stdexcept>
int main(int argc, char *argv[])
{
int Result = EXIT_SUCCESS;
try
{
App theApp;
theApp.Run();
}
catch (const std::exception& e)
{
printf("Error: %s\n", e.what());
Result = EXIT_FAILURE;
}
catch (...)
{
printf("Unhandled exception\n");
Result = EXIT_FAILURE;
}
system("PAUSE");
return Result;
}
#include "Video_Mode.hpp"
#include <vector>
#include <algorithm>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
namespace
{
typedef std::vector<Video_Mode> Video_Mode_List;
Video_Mode_List Supported_Modes;
struct Compare_Modes
{
bool operator()(const Video_Mode &Mode_1, const Video_Mode &Mode_2) const
{
if (Mode_1.Bits_Per_Pixel > Mode_2.Bits_Per_Pixel)
return true;
else if (Mode_1.Bits_Per_Pixel < Mode_2.Bits_Per_Pixel)
return false;
else if (Mode_1.Width > Mode_2.Width)
return true;
else if (Mode_1.Width < Mode_2.Width)
return false;
else
return Mode_1.Height > Mode_2.Height;
}
};
}
Video_Mode::Video_Mode() : Width(0),
Height(0),
Bits_Per_Pixel(0)
{
}
Video_Mode::Video_Mode(unsigned int The_Width, unsigned int The_Height, unsigned int The_Bits_Per_Pixel)
: Width(The_Width),
Height(The_Height),
Bits_Per_Pixel(The_Bits_Per_Pixel)
{
}
Video_Mode Video_Mode::Get_Desktop_Mode()
{
DEVMODE Device_Mode = {0};
Device_Mode.dmSize = sizeof(Device_Mode);
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &Device_Mode);
return Video_Mode(Device_Mode.dmPelsWidth, Device_Mode.dmPelsHeight, Device_Mode.dmBitsPerPel);
}
std::size_t Video_Mode::Get_Mode_Count()
{
Initialize_Modes();
return Supported_Modes.size();
}
Video_Mode Video_Mode::Get_Mode(std::size_t Index)
{
Initialize_Modes();
return Supported_Modes[Index];
}
bool Video_Mode::Is_Valid() const
{
Initialize_Modes();
return Supported_Modes.end() != std::find(Supported_Modes.begin(), Supported_Modes.end(), *this);
}
bool Video_Mode::operator==(const Video_Mode &Mode) const
{
return (Width == Mode.Width
&& Height == Mode.Height
&& Bits_Per_Pixel == Mode.Bits_Per_Pixel);
}
bool Video_Mode::operator!=(const Video_Mode &Mode) const
{
return !(*this == Mode);
}
void Video_Mode::Initialize_Modes()
{
static bool Initialized = false;
if (!Initialized)
{
DEVMODE Device_Mode = {0};
Device_Mode.dmSize = sizeof(Device_Mode);
for (std::size_t i = 0; 0 != EnumDisplaySettings(NULL, i, &Device_Mode); ++i)
{
Video_Mode Mode(Device_Mode.dmPelsWidth, Device_Mode.dmPelsHeight, Device_Mode.dmBitsPerPel);
if (Supported_Modes.end() == std::find(Supported_Modes.begin(), Supported_Modes.end(), Mode))
Supported_Modes.push_back(Mode);
}
std::sort(Supported_Modes.begin(), Supported_Modes.end(), Compare_Modes());
}
}
#include "Window.hpp"
#include <gl/GL.h>
#pragma comment(lib, "opengl32.lib")
const wchar_t *Window::Window_Class_Name = L"GLTSF";
Window::Window() : my_Handle(0),
my_Device_Context(0),
my_GL_Context(0),
my_Class_Registered(false),
my_Listener(0)
{
}
Window::~Window()
{
Finalize();
Show_Cursor();
}
void Window::Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen)
{
Finalize();
my_Video_Mode = Mode;
if (!my_Video_Mode.Is_Valid())
throw std::runtime_error("Invalid video mode");
my_Fullscreen = Fullscreen;
Register_Class();
Create_Window(Title, Mode, Fullscreen);
Show();
my_IMM.Initialize(my_Handle);
}
void Window::Finalize()
{
my_IMM.Finalize();
Destroy_Window();
Unregister_Class();
}
void Window::Set_Listener(Window_Listener *Listener)
{
my_Listener = Listener;
}
void Window::Show()
{
if (my_Handle)
ShowWindow(my_Handle, SW_SHOW);
}
void Window::Hide()
{
if (my_Handle)
ShowWindow(my_Handle, SW_HIDE);
}
void Window::Handle_Events()
{
MSG Message = {0};
while (PeekMessageW(&Message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessageW(&Message);
}
}
void Window::Display()
{
if (my_Device_Context && my_GL_Context)
SwapBuffers(my_Device_Context);
}
void Window::Show_Cursor()
{
ShowCursor(TRUE);
}
void Window::Hide_Cursor()
{
ShowCursor(FALSE);
}
HWND Window::Get_Handle()
{
return my_Handle;
}
IMM & Window::Get_IMM()
{
return my_IMM;
}
void Window::Register_Class()
{
WNDCLASSEXW Window_Class = {0};
Window_Class.cbSize = sizeof(Window_Class);
Window_Class.style = 0;
Window_Class.lpfnWndProc = &Window::Window_Procedure;
Window_Class.cbClsExtra = 0;
Window_Class.cbWndExtra = 0;
Window_Class.hInstance = GetModuleHandle(NULL);
Window_Class.hIcon = NULL;
Window_Class.hCursor = NULL;
Window_Class.hbrBackground = NULL;
Window_Class.lpszMenuName = NULL;
Window_Class.lpszClassName = Window_Class_Name;
Window_Class.hIconSm = NULL;
if (0 == RegisterClassExW(&Window_Class))
throw std::runtime_error("Failed to register window class");
my_Class_Registered = true;
}
void Window::Unregister_Class()
{
if (my_Class_Registered)
{
if (0 == UnregisterClassW(Window_Class_Name, GetModuleHandle(NULL)))
printf("Warning: Failed to unregister window class\n");
my_Class_Registered = false;
}
}
void Window::Create_Window(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen)
{
HDC Screen_DC = GetDC(NULL);
int Left = (GetDeviceCaps(Screen_DC, HORZRES) - my_Video_Mode.Width) / 2;
int Top = (GetDeviceCaps(Screen_DC, VERTRES) - my_Video_Mode.Height) / 2;
int Width = my_Video_Mode.Width;
int Height = my_Video_Mode.Height;
ReleaseDC(NULL, Screen_DC);
DWORD Style = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
if (!my_Fullscreen)
{
RECT Rect = {0, 0, Width, Height};
AdjustWindowRect(&Rect, Style, false);
Width = Rect.right - Rect.left;
Height = Rect.bottom - Rect.top;
}
my_Handle = CreateWindowW(Window_Class_Name, Title.c_str(), Style, Left, Top, Width, Height, NULL, NULL, GetModuleHandle(NULL), this);
if (!my_Handle)
throw std::runtime_error("Failed to create window");
if (Fullscreen)
Switch_To_Fullscreen(Mode);
Create_Context(Mode);
RECT Rect = {0};
GetClientRect(my_Handle, &Rect);
//TODO: ...
}
void Window::Destroy_Window()
{
Destroy_Context();
if (my_Handle)
{
DestroyWindow(my_Handle);
my_Handle = 0;
if (my_Fullscreen)
ChangeDisplaySettings(NULL, 0);
}
}
void Window::Create_Context(const Video_Mode &Mode)
{
my_Device_Context = GetDC(my_Handle);
if (!my_Device_Context)
throw std::runtime_error("Failed to get device context");
PIXELFORMATDESCRIPTOR Pixel_Descriptor = {0};
Pixel_Descriptor.nSize = sizeof(Pixel_Descriptor);
Pixel_Descriptor.nVersion = 1;
Pixel_Descriptor.iLayerType = PFD_MAIN_PLANE;
Pixel_Descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
Pixel_Descriptor.iPixelType = PFD_TYPE_RGBA;
Pixel_Descriptor.cColorBits = static_cast<BYTE>(Mode.Bits_Per_Pixel);
Pixel_Descriptor.cDepthBits = 24;
Pixel_Descriptor.cStencilBits = 8;
Pixel_Descriptor.cAlphaBits = Mode.Bits_Per_Pixel == 32 ? 8 : 0;
int Best_Format = ChoosePixelFormat(my_Device_Context, &Pixel_Descriptor);
if (0 == Best_Format)
throw std::runtime_error("Failed to find suitable pixel format");
PIXELFORMATDESCRIPTOR Actual_Format = {0};
Actual_Format.nSize = sizeof(Actual_Format);
Actual_Format.nVersion = 1;
DescribePixelFormat(my_Device_Context, Best_Format, sizeof(Actual_Format), &Actual_Format);
if (!SetPixelFormat(my_Device_Context, Best_Format, &Actual_Format))
throw std::runtime_error("Failed to set device pixel format");
my_GL_Context = wglCreateContext(my_Device_Context);
if (!my_GL_Context)
throw std::runtime_error("Failed to create OpenGL context");
wglMakeCurrent(my_Device_Context, my_GL_Context);
}
void Window::Destroy_Context()
{
if (my_GL_Context)
{
wglDeleteContext(my_GL_Context);
my_GL_Context = 0;
}
if (my_Device_Context)
{
ReleaseDC(my_Handle, my_Device_Context);
my_Device_Context = 0;
}
}
void Window::Switch_To_Fullscreen(const Video_Mode &Mode)
{
DEVMODE Device_Mode = {0};
Device_Mode.dmSize = sizeof(Device_Mode);
Device_Mode.dmPelsWidth = Mode.Width;
Device_Mode.dmPelsHeight = Mode.Height;
Device_Mode.dmBitsPerPel = Mode.Bits_Per_Pixel;
Device_Mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings(&Device_Mode, CDS_FULLSCREEN))
throw std::runtime_error("Failed to change to fullscreen mode");
SetWindowLong(my_Handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
SetWindowLong(my_Handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
SetWindowPos(my_Handle, HWND_TOP, 0, 0, Mode.Width, Mode.Height, SWP_FRAMECHANGED);
}
LRESULT CALLBACK Window::Window_Procedure(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_CREATE:
{
LONG This = reinterpret_cast<LONG>(reinterpret_cast<CREATESTRUCT *>(lParam)->lpCreateParams);
SetWindowLongPtr(Handle, GWLP_USERDATA, This);
return 0;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
default:
{
Window* Win = reinterpret_cast<Window *>(GetWindowLongPtr(Handle, GWLP_USERDATA));
if (Win)
return Win->Handle_Message(Handle, Message, wParam, lParam);
}
break;
}
return DefWindowProcW(Handle, Message, wParam, lParam);
}
#define Call_Listener(x)\
if (my_Listener) my_Listener->x
LRESULT Window::Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam)
{
bool IMM_Message = false;
LRESULT Result = my_IMM.Handle_Message(Handle, Message, wParam, lParam, IMM_Message);
if (IMM_Message)
return Result;
switch (Message)
{
case WM_SIZE:
Call_Listener(On_Resized(LOWORD(lParam), HIWORD(lParam)));
break;
case WM_CLOSE:
Call_Listener(On_Close());
break;
case WM_KEYDOWN:
Call_Listener(On_Key_Down(wParam));
break;
case WM_KEYUP:
Call_Listener(On_Key_Up(wParam));
break;
case WM_CHAR:
Call_Listener(On_Char(wParam));
break;
case WM_SETFOCUS:
my_IMM.Focus_Gained();
break;
case WM_KILLFOCUS:
my_IMM.Focus_Lost();
break;
case WM_LBUTTONDOWN:
Call_Listener(On_Mouse_Button_Down(Mouse_Button_Left));
break;
case WM_LBUTTONUP:
Call_Listener(On_Mouse_Button_Up(Mouse_Button_Left));
break;
case WM_RBUTTONDOWN:
Call_Listener(On_Mouse_Button_Down(Mouse_Button_Right));
break;
case WM_RBUTTONUP:
Call_Listener(On_Mouse_Button_Up(Mouse_Button_Right));
break;
default:
return DefWindowProcW(Handle, Message, wParam, lParam);
break;
}
return 0;
}

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GLTSF", "GLTSF.vcxproj", "{790D58BA-E5F6-4286-A9C6-0DC28779789D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{790D58BA-E5F6-4286-A9C6-0DC28779789D}.Debug|Win32.ActiveCfg = Debug|Win32
{790D58BA-E5F6-4286-A9C6-0DC28779789D}.Debug|Win32.Build.0 = Debug|Win32
{790D58BA-E5F6-4286-A9C6-0DC28779789D}.Release|Win32.ActiveCfg = Release|Win32
{790D58BA-E5F6-4286-A9C6-0DC28779789D}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="GLTSF"
ProjectGUID="{FC8A9A48-6667-4BDE-8E9B-5859408AEE83}"
RootNamespace="GLTSF"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)bin"
IntermediateDirectory="obj\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)bin"
IntermediateDirectory="obj\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\src\App.cpp"
>
</File>
<File
RelativePath=".\src\Main.cpp"
>
</File>
<File
RelativePath=".\src\TSF.cpp"
>
</File>
<File
RelativePath=".\src\Video_Mode.cpp"
>
</File>
<File
RelativePath=".\src\Window.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\include\App.hpp"
>
</File>
<File
RelativePath=".\include\TSF.hpp"
>
</File>
<File
RelativePath=".\include\Video_Mode.hpp"
>
</File>
<File
RelativePath=".\include\Window.hpp"
>
</File>
<File
RelativePath=".\include\Window_Listener.hpp"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{790D58BA-E5F6-4286-A9C6-0DC28779789D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>GLTSF</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="include\App.hpp" />
<ClInclude Include="include\TSF.hpp" />
<ClInclude Include="include\Video_Mode.hpp" />
<ClInclude Include="include\Window.hpp" />
<ClInclude Include="include\Window_Listener.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\App.cpp" />
<ClCompile Include="src\Main.cpp" />
<ClCompile Include="src\TSF.cpp" />
<ClCompile Include="src\Video_Mode.cpp" />
<ClCompile Include="src\Window.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\App.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Video_Mode.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Window.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Window_Listener.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\TSF.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\App.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Video_Mode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Window.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\TSF.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GLTSF", "GLTSF.vcproj", "{FC8A9A48-6667-4BDE-8E9B-5859408AEE83}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FC8A9A48-6667-4BDE-8E9B-5859408AEE83}.Debug|Win32.ActiveCfg = Debug|Win32
{FC8A9A48-6667-4BDE-8E9B-5859408AEE83}.Debug|Win32.Build.0 = Debug|Win32
{FC8A9A48-6667-4BDE-8E9B-5859408AEE83}.Release|Win32.ActiveCfg = Release|Win32
{FC8A9A48-6667-4BDE-8E9B-5859408AEE83}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
#ifndef APP_HPP
#define APP_HPP
#include "Window.hpp"
class App : public Window_Listener
{
public:
App();
virtual ~App();
void Initialize();
void Finalize();
void Run();
virtual void On_Close();
virtual void On_Key_Down(int Key);
virtual void On_Key_Up(int Key);
virtual void On_Char(unsigned int Char);
virtual void On_Resized(unsigned int Width, unsigned int Height);
private:
void Update();
void Draw();
static const int Width = 800;
static const int Height = 600;
static const int Bits_Per_Pixel = 32;
static const bool Fullscreen = true;
Window my_Window;
bool my_Done;
};
#endif
#ifndef TSF_HPP
#define TSF_HPP
#include <msctf.h>
#include <atlbase.h>
class TSF
{
public:
static void Initialize();
static void Finalize();
private:
class TSF_Text_Store : public ITextStoreACP, public ITfContextOwnerCompositionSink
{
public:
//IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
//ITextStoreACP
STDMETHODIMP AdviseSink(REFIID riid, IUnknown *punk, DWORD dwMask);
STDMETHODIMP UnadviseSink(IUnknown *punk);
STDMETHODIMP RequestLock(DWORD dwLockFlags, HRESULT *phrSession);
STDMETHODIMP GetStatus(TS_STATUS *pdcs);
STDMETHODIMP QueryInsert(LONG acpTestStart, LONG acpTestEnd, ULONG cch, LONG *pacpResultStart, LONG *pacpResultEnd);
STDMETHODIMP GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched);
STDMETHODIMP SetSelection(ULONG ulCount, const TS_SELECTION_ACP *pSelection);
STDMETHODIMP GetText(LONG acpStart, LONG acpEnd, WCHAR *pchPlain, ULONG cchPlainReq, ULONG *pcchPlainRet, TS_RUNINFO *prgRunInfo, ULONG cRunInfoReq, ULONG *pcRunInfoRet, LONG *pacpNext);
STDMETHODIMP SetText(DWORD dwFlags, LONG acpStart, LONG acpEnd, const WCHAR *pchText, ULONG cch, TS_TEXTCHANGE *pChange);
STDMETHODIMP GetFormattedText(LONG acpStart, LONG acpEnd, IDataObject **ppDataObject);
STDMETHODIMP GetEmbedded(LONG acpPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk);
STDMETHODIMP QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable);
STDMETHODIMP InsertEmbedded(DWORD dwFlags, LONG acpStart, LONG acpEnd, IDataObject *pDataObject, TS_TEXTCHANGE *pChange);
STDMETHODIMP InsertTextAtSelection(DWORD dwFlags, const WCHAR *pchText, ULONG cch, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange);
STDMETHODIMP InsertEmbeddedAtSelection(DWORD dwFlags, IDataObject *pDataObject, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange);
STDMETHODIMP RequestSupportedAttrs(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs);
STDMETHODIMP RequestAttrsAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags);
STDMETHODIMP RequestAttrsTransitioningAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags);
STDMETHODIMP FindNextAttrTransition(LONG acpStart, LONG acpHalt, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags, LONG *pacpNext, BOOL *pfFound, LONG *plFoundOffset);
STDMETHODIMP RetrieveRequestedAttrs(ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched);
STDMETHODIMP GetEndACP(LONG *pacp);
STDMETHODIMP GetActiveView(TsViewCookie *pvcView);
STDMETHODIMP GetACPFromPoint(TsViewCookie vcView, const POINT *ptScreen, DWORD dwFlags, LONG *pacp);
STDMETHODIMP GetTextExt(TsViewCookie vcView, LONG acpStart, LONG acpEnd, RECT *prc, BOOL *pfClipped);
STDMETHODIMP GetScreenExt(TsViewCookie vcView, RECT *prc);
STDMETHODIMP GetWnd(TsViewCookie vcView, HWND *phwnd);
//ITfOwnerCompositionSink
STDMETHODIMP OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk);
STDMETHODIMP OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew);
STDMETHODIMP OnEndComposition(ITfCompositionView *pComposition);
void Initialize();
void Finalize();
TSF_Text_Store();
~TSF_Text_Store();
private:
ULONG my_Reference_Count;
CComPtr<ITfDocumentMgr> my_Document_Manager;
CComPtr<ITfContext> my_Context;
DWORD my_Edit_Cookie;
CComPtr<ITextStoreACPSink> my_Sink;
DWORD my_Sink_Mask;
DWORD my_Lock;
DWORD my_Lock_Queued;
CComPtr<ITfCompositionView> my_Composition_View;
TS_SELECTION_ACP my_Composition_Selection;
};
TSF();
static bool COM_Initialized;
static CComPtr<ITfThreadMgr> Thread_Manager;
static TfClientId Client_Id;
static TSF_Text_Store *Text_Store;
};
#endif
#ifndef VIDEO_MODE_HPP
#define VIDEO_MODE_HPP
#include <cstddef>
class Video_Mode
{
public:
Video_Mode();
Video_Mode(unsigned int The_Width, unsigned int The_Height, unsigned int The_Bits_Per_Pixel);
static Video_Mode Get_Desktop_Mode();
static std::size_t Get_Mode_Count();
static Video_Mode Get_Mode(std::size_t Index);
bool Is_Valid() const;
bool operator==(const Video_Mode &Mode) const;
bool operator!=(const Video_Mode &Mode) const;
unsigned int Width;
unsigned int Height;
unsigned int Bits_Per_Pixel;
private:
static void Initialize_Modes();
};
#endif
#ifndef WINDOW_HPP
#define WINDOW_HPP
#include <string>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "Video_Mode.hpp"
#include "Window_Listener.hpp"
#include "TSF.hpp"
class Window
{
public:
Window();
~Window();
void Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen);
void Finalize();
void Set_Listener(Window_Listener *Listener);
void Show();
void Hide();
void Handle_Events();
void Display();
void Show_Cursor();
void Hide_Cursor();
private:
static const wchar_t *Window_Class_Name;
void Register_Class();
void Unregister_Class();
void Create_Window(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen);
void Destroy_Window();
void Create_Context(const Video_Mode &Mode);
void Destroy_Context();
void Switch_To_Fullscreen(const Video_Mode &Mode);
LRESULT Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK Window_Procedure(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam);
HWND my_Handle;
Video_Mode my_Video_Mode;
bool my_Fullscreen;
HDC my_Device_Context;
HGLRC my_GL_Context;
bool my_Class_Registered;
Window_Listener *my_Listener;
};
#endif
#ifndef WINDOW_LISTENER_HPP
#define WINDOW_LISTENER_HPP
class Window_Listener
{
public:
virtual void On_Close(){}
virtual void On_Key_Down(int Key){}
virtual void On_Key_Up(int Key){}
virtual void On_Char(unsigned int Char){}
virtual void On_Resized(unsigned int Width, unsigned int Height){}
};
#endif
#include "App.hpp"
#include "TSF.hpp"
#include <GL/gl.h>
#include <GL/glu.h>
#pragma comment(lib, "glu32.lib")
GLfloat Rotation = 0.0f;
App::App() : my_Done(false)
{
TSF::Initialize();
}
App::~App()
{
Finalize();
TSF::Finalize();
}
void App::Initialize()
{
Finalize();
my_Window.Initialize(L"GLTSF", Video_Mode(Width, Height, Bits_Per_Pixel), Fullscreen);
my_Window.Set_Listener(this);
my_Window.Show();
my_Window.Hide_Cursor();
}
void App::Finalize()
{
my_Window.Finalize();
}
void App::Run()
{
Initialize();
while (!my_Done)
{
my_Window.Handle_Events();
Update();
Draw();
my_Window.Display();
}
}
void App::On_Close()
{
my_Done = true;
my_Window.Hide();
}
void App::On_Key_Down(int Key)
{
switch (Key)
{
case VK_ESCAPE:
On_Close();
break;
}
}
void App::On_Key_Up(int Key)
{
}
void App::On_Char(unsigned int Char)
{
printf("Char: U+%04X\n", Char);
}
void App::On_Resized(unsigned int Width, unsigned int Height)
{
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void App::Update()
{
Rotation += 0.2f;
}
void App::Draw()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glRotatef(Rotation, 0.0f, 0.0f, -1.0f);
glBegin(GL_TRIANGLES);
glColor3f(0.7f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
glColor3f(0.0f, 0.7f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.0f);
glColor3f(0.0f, 0.0f, 0.7f);
glVertex3f(0.5f, -0.5f, 0.0f);
glEnd();
}
#include "App.hpp"
#include <stdexcept>
int main(int argc, char *argv[])
{
int Result = EXIT_SUCCESS;
try
{
App theApp;
theApp.Run();
}
catch (const std::exception& e)
{
printf("Error: %s\n", e.what());
Result = EXIT_FAILURE;
}
catch (...)
{
printf("Unhandled exception\n");
Result = EXIT_FAILURE;
}
system("PAUSE");
return Result;
}
#include "TSF.hpp"
#include <stdexcept>
bool TSF::COM_Initialized = false;
CComPtr<ITfThreadMgr> TSF::Thread_Manager;
TfClientId TSF::Client_Id;
TSF::TSF_Text_Store *TSF::Text_Store = NULL;
void TSF::Initialize()
{
if (!COM_Initialized)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (S_OK != hr && S_FALSE != hr)
throw std::runtime_error("Failed to initialize COM");
COM_Initialized = true;
}
if (!Thread_Manager)
{
if (FAILED(CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfThreadMgr, reinterpret_cast<void **>(&Thread_Manager))))
throw std::runtime_error("Failed to create ITfThreadMgr instance");
if (FAILED(Thread_Manager->Activate(&Client_Id)))
throw std::runtime_error("ITfThreadMgr::Activate failed");
Text_Store = new TSF_Text_Store;
Text_Store->Initialize();
}
}
void TSF::Finalize()
{
if (Thread_Manager)
{
Thread_Manager->Deactivate();
Thread_Manager = NULL;
}
if (COM_Initialized)
{
CoUninitialize();
COM_Initialized = false;
}
}
STDMETHODIMP TSF::TSF_Text_Store::QueryInterface(REFIID riid, void **ppvObject)
{
*ppvObject = NULL;
if (IID_IUnknown == riid || IID_ITextStoreACP == riid)
*ppvObject = static_cast<ITextStoreACP *>(this);
else if (IID_ITfContextOwnerCompositionSink == riid)
*ppvObject = static_cast<ITfContextOwnerCompositionSink *>(this);
if (*ppvObject)
{
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) TSF::TSF_Text_Store::AddRef()
{
return ++my_Reference_Count;
}
STDMETHODIMP_(ULONG) TSF::TSF_Text_Store::Release()
{
--my_Reference_Count;
if (0 != my_Reference_Count)
return my_Reference_Count;
delete this;
return 0;
}
#define CHECK_CONDITION(condition, retval, function, line) \
if (!condition) \
{ \
printf("%s:%d: Condition failure: %s\n", function, line, #condition); \
}
#define ENSURE(condition, retval) CHECK_CONDITION(condition, retval, __FUNCTION__, __LINE__)
STDMETHODIMP TSF::TSF_Text_Store::AdviseSink(REFIID riid, IUnknown *punk, DWORD dwMask)
{
ENSURE(punk && IID_ITextStoreACP == riid, E_INVALIDARG);
if (!my_Sink)
{
HRESULT hr = punk->QueryInterface(&my_Sink);
ENSURE(SUCCEEDED(hr) && my_Sink, E_UNEXPECTED);
}
else
{
CComPtr<IUnknown> Unknown_1, Unknown_2;
punk->QueryInterface(&Unknown_1);
my_Sink->QueryInterface(&Unknown_2);
if (Unknown_1 != Unknown_2)
return CONNECT_E_ADVISELIMIT;
}
my_Sink_Mask = dwMask;
return S_OK;
}
STDMETHODIMP TSF::TSF_Text_Store::UnadviseSink(IUnknown *punk)
{
ENSURE(punk, E_INVALIDARG);
ENSURE(my_Sink, CONNECT_E_NOCONNECTION);
CComPtr<IUnknown> Unknown_1, Unknown_2;
punk->QueryInterface(&Unknown_1);
my_Sink->QueryInterface(&Unknown_2);
if (Unknown_1 != Unknown_2)
return CONNECT_E_NOCONNECTION;
my_Sink = NULL;
my_Sink_Mask = 0;
return S_OK;
}
STDMETHODIMP TSF::TSF_Text_Store::RequestLock(DWORD dwLockFlags, HRESULT *phrSession)
{
ENSURE(my_Sink, E_FAIL);
ENSURE(phrSession, E_INVALIDARG);
if (my_Lock)
{
if (TS_LF_READ == (my_Lock & TS_LF_READWRITE)
&& TS_LF_READWRITE == (dwLockFlags & TS_LF_READWRITE)
&& !(dwLockFlags & TS_LF_SYNC))
{
*phrSession = TS_S_ASYNC;
my_Lock_Queued = dwLockFlags & (~TS_LF_SYNC);
}
else
{
*phrSession = TS_E_SYNCHRONOUS;
return E_FAIL;
}
}
else
{
my_Lock = dwLockFlags & (~TS_LF_SYNC);
*phrSession = my_Sink->OnLockGranted(my_Lock);
while (my_Lock_Queued)
{
my_Lock = my_Lock_Queued;
my_Lock_Queued = 0;
my_Sink->OnLockGranted(my_Lock);
}
my_Lock = 0;
}
return S_OK;
}
STDMETHODIMP TSF::TSF_Text_Store::GetStatus(TS_STATUS *pdcs)
{
ENSURE(pdcs, E_INVALIDARG);
pdcs->dwDynamicFlags = 0;
pdcs->dwStaticFlags = TS_SS_NOHIDDENTEXT;
return S_OK;
}
STDMETHODIMP TSF::TSF_Text_Store::QueryInsert(LONG acpTestStart, LONG acpTestEnd, ULONG cch, LONG *pacpResultStart, LONG *pacpResultEnd)
{
ENSURE(0 <= acpTestStart && acpTestStart <= acpTestEnd && pacpResultStart && pacpResultEnd, E_INVALIDARG);
*pacpResultStart = acpTestStart;
*pacpResultEnd = acpTestStart + cch;
return S_OK;
}
STDMETHODIMP TSF::TSF_Text_Store::GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched)
{
ENSURE(TS_LF_READ == (my_Lock && TS_LF_READ), TS_E_NOLOCK);
ENSURE(ulCount && pSelection && pcFetched, E_INVALIDARG);
*pcFetched = 0;
ENSURE(TS_DEFAULT_SELECTION == ulIndex || 0 == ulIndex, TS_E_NOSELECTION);
if (my_Composition_View)
{
*pSelection = my_Composition_Selection;
}
else
{
//TODO
}
*pcFetched = 1;
return S_OK;
}
STDMETHODIMP TSF::TSF_Text_Store::SetSelection(ULONG ulCount, const TS_SELECTION_ACP *pSelection)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::GetText(LONG acpStart, LONG acpEnd, WCHAR *pchPlain, ULONG cchPlainReq, ULONG *pcchPlainRet, TS_RUNINFO *prgRunInfo, ULONG cRunInfoReq, ULONG *pcRunInfoRet, LONG *pacpNext)
{
ENSURE(TS_LF_READ == (my_Lock & TS_LF_READ), TS_E_NOLOCK);
ENSURE(pcchPlainRet && (pchPlain || prgRunInfo)
&& (!cchPlainReq == !pchPlain)
&& (!cRunInfoReq == !prgRunInfo), E_INVALIDARG);
ENSURE(0 <= acpStart && -1 <= acpEnd
&& (-1 == acpEnd || acpStart <= acpEnd), TS_E_INVALIDPOS);
*pcchPlainRet = 0;
if (pchPlain && cchPlainReq) *pchPlain = 0;
if (pcRunInfoRet) *pcRunInfoRet = 0;
//TODO
return S_OK;
}
STDMETHODIMP TSF::TSF_Text_Store::SetText(DWORD dwFlags, LONG acpStart, LONG acpEnd, const WCHAR *pchText, ULONG cch, TS_TEXTCHANGE *pChange)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::GetFormattedText(LONG acpStart, LONG acpEnd, IDataObject **ppDataObject)
{
//not needed
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::GetEmbedded(LONG acpPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk)
{
//not needed
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable)
{
if (!pfInsertable)
return E_INVALIDARG;
//Not supported
*pfInsertable = FALSE;
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::InsertEmbedded(DWORD dwFlags, LONG acpStart, LONG acpEnd, IDataObject *pDataObject, TS_TEXTCHANGE *pChange)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::InsertTextAtSelection(DWORD dwFlags, const WCHAR *pchText, ULONG cch, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::InsertEmbeddedAtSelection(DWORD dwFlags, IDataObject *pDataObject, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange)
{
//not needed
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::RequestSupportedAttrs(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs)
{
//not needed
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::RequestAttrsAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags)
{
//not needed
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::RequestAttrsTransitioningAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags)
{
//not needed
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::FindNextAttrTransition(LONG acpStart, LONG acpHalt, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags, LONG *pacpNext, BOOL *pfFound, LONG *plFoundOffset)
{
//not needed
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::RetrieveRequestedAttrs(ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched)
{
//not needed
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::GetEndACP(LONG *pacp)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::GetActiveView(TsViewCookie *pvcView)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::GetACPFromPoint(TsViewCookie vcView, const POINT *ptScreen, DWORD dwFlags, LONG *pacp)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::GetTextExt(TsViewCookie vcView, LONG acpStart, LONG acpEnd, RECT *prc, BOOL *pfClipped)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::GetScreenExt(TsViewCookie vcView, RECT *prc)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::GetWnd(TsViewCookie vcView, HWND *phwnd)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew)
{
return E_NOTIMPL;
}
STDMETHODIMP TSF::TSF_Text_Store::OnEndComposition(ITfCompositionView *pComposition)
{
return E_NOTIMPL;
}
TSF::TSF_Text_Store::TSF_Text_Store() : my_Reference_Count(1),
my_Edit_Cookie(0),
my_Lock(0),
my_Lock_Queued(0)
{
}
TSF::TSF_Text_Store::~TSF_Text_Store()
{
}
void TSF::TSF_Text_Store::Initialize()
{
if (FAILED(Thread_Manager->CreateDocumentMgr(&my_Document_Manager)))
throw std::runtime_error("Failed to create document manager");
if (FAILED(my_Document_Manager->CreateContext(Client_Id, 0, static_cast<ITextStoreACP *>(this), &my_Context, &my_Edit_Cookie)))
throw std::runtime_error("Failed to create document context");
if (FAILED(my_Document_Manager->Push(my_Context)))
throw std::runtime_error("Failed to push context");
}
void TSF::TSF_Text_Store::Finalize()
{
}
#include "Video_Mode.hpp"
#include <vector>
#include <algorithm>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
namespace
{
typedef std::vector<Video_Mode> Video_Mode_List;
Video_Mode_List Supported_Modes;
struct Compare_Modes
{
bool operator()(const Video_Mode &Mode_1, const Video_Mode &Mode_2) const
{
if (Mode_1.Bits_Per_Pixel > Mode_2.Bits_Per_Pixel)
return true;
else if (Mode_1.Bits_Per_Pixel < Mode_2.Bits_Per_Pixel)
return false;
else if (Mode_1.Width > Mode_2.Width)
return true;
else if (Mode_1.Width < Mode_2.Width)
return false;
else
return Mode_1.Height > Mode_2.Height;
}
};
}
Video_Mode::Video_Mode() : Width(0),
Height(0),
Bits_Per_Pixel(0)
{
}
Video_Mode::Video_Mode(unsigned int The_Width, unsigned int The_Height, unsigned int The_Bits_Per_Pixel)
: Width(The_Width),
Height(The_Height),
Bits_Per_Pixel(The_Bits_Per_Pixel)
{
}
Video_Mode Video_Mode::Get_Desktop_Mode()
{
DEVMODE Device_Mode = {0};
Device_Mode.dmSize = sizeof(Device_Mode);
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &Device_Mode);
return Video_Mode(Device_Mode.dmPelsWidth, Device_Mode.dmPelsHeight, Device_Mode.dmBitsPerPel);
}
std::size_t Video_Mode::Get_Mode_Count()
{
Initialize_Modes();
return Supported_Modes.size();
}
Video_Mode Video_Mode::Get_Mode(std::size_t Index)
{
Initialize_Modes();
return Supported_Modes[Index];
}
bool Video_Mode::Is_Valid() const
{
Initialize_Modes();
return Supported_Modes.end() != std::find(Supported_Modes.begin(), Supported_Modes.end(), *this);
}
bool Video_Mode::operator==(const Video_Mode &Mode) const
{
return (Width == Mode.Width
&& Height == Mode.Height
&& Bits_Per_Pixel == Mode.Bits_Per_Pixel);
}
bool Video_Mode::operator!=(const Video_Mode &Mode) const
{
return !(*this == Mode);
}
void Video_Mode::Initialize_Modes()
{
static bool Initialized = false;
if (!Initialized)
{
DEVMODE Device_Mode = {0};
Device_Mode.dmSize = sizeof(Device_Mode);
for (std::size_t i = 0; 0 != EnumDisplaySettings(NULL, i, &Device_Mode); ++i)
{
Video_Mode Mode(Device_Mode.dmPelsWidth, Device_Mode.dmPelsHeight, Device_Mode.dmBitsPerPel);
if (Supported_Modes.end() == std::find(Supported_Modes.begin(), Supported_Modes.end(), Mode))
Supported_Modes.push_back(Mode);
}
std::sort(Supported_Modes.begin(), Supported_Modes.end(), Compare_Modes());
}
}
#include "Window.hpp"
#include <gl/GL.h>
#pragma comment(lib, "opengl32.lib")
const wchar_t *Window::Window_Class_Name = L"GLTSF";
Window::Window() : my_Handle(0),
my_Device_Context(0),
my_GL_Context(0),
my_Class_Registered(false),
my_Listener(0)
{
}
Window::~Window()
{
Finalize();
Show_Cursor();
}
void Window::Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen)
{
Finalize();
my_Video_Mode = Mode;
if (!my_Video_Mode.Is_Valid())
throw std::runtime_error("Invalid video mode");
my_Fullscreen = Fullscreen;
Register_Class();
Create_Window(Title, Mode, Fullscreen);
}
void Window::Finalize()
{
Destroy_Window();
Unregister_Class();
}
void Window::Set_Listener(Window_Listener *Listener)
{
my_Listener = Listener;
}
void Window::Register_Class()
{
WNDCLASSEXW Window_Class = {0};
Window_Class.cbSize = sizeof(Window_Class);
Window_Class.style = 0;
Window_Class.lpfnWndProc = &Window::Window_Procedure;
Window_Class.cbClsExtra = 0;
Window_Class.cbWndExtra = 0;
Window_Class.hInstance = GetModuleHandle(NULL);
Window_Class.hIcon = NULL;
Window_Class.hCursor = NULL;
Window_Class.hbrBackground = NULL;
Window_Class.lpszMenuName = NULL;
Window_Class.lpszClassName = Window_Class_Name;
Window_Class.hIconSm = NULL;
if (0 == RegisterClassExW(&Window_Class))
throw std::runtime_error("Failed to register window class");
my_Class_Registered = true;
}
void Window::Unregister_Class()
{
if (my_Class_Registered)
{
if (0 == UnregisterClassW(Window_Class_Name, GetModuleHandle(NULL)))
printf("Warning: Failed to unregister window class\n");
my_Class_Registered = false;
}
}
void Window::Create_Window(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen)
{
HDC Screen_DC = GetDC(NULL);
int Left = (GetDeviceCaps(Screen_DC, HORZRES) - my_Video_Mode.Width) / 2;
int Top = (GetDeviceCaps(Screen_DC, VERTRES) - my_Video_Mode.Height) / 2;
int Width = my_Video_Mode.Width;
int Height = my_Video_Mode.Height;
ReleaseDC(NULL, Screen_DC);
DWORD Style = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
if (!my_Fullscreen)
{
RECT Rect = {0, 0, Width, Height};
AdjustWindowRect(&Rect, Style, false);
Width = Rect.right - Rect.left;
Height = Rect.bottom - Rect.top;
}
my_Handle = CreateWindowW(Window_Class_Name, Title.c_str(), Style, Left, Top, Width, Height, NULL, NULL, GetModuleHandle(NULL), this);
if (!my_Handle)
throw std::runtime_error("Failed to create window");
if (Fullscreen)
Switch_To_Fullscreen(Mode);
Create_Context(Mode);
RECT Rect = {0};
GetClientRect(my_Handle, &Rect);
//TODO: ...
}
void Window::Destroy_Window()
{
Destroy_Context();
if (my_Handle)
{
DestroyWindow(my_Handle);
my_Handle = 0;
if (my_Fullscreen)
ChangeDisplaySettings(NULL, 0);
}
}
void Window::Create_Context(const Video_Mode &Mode)
{
my_Device_Context = GetDC(my_Handle);
if (!my_Device_Context)
throw std::runtime_error("Failed to get device context");
PIXELFORMATDESCRIPTOR Pixel_Descriptor = {0};
Pixel_Descriptor.nSize = sizeof(Pixel_Descriptor);
Pixel_Descriptor.nVersion = 1;
Pixel_Descriptor.iLayerType = PFD_MAIN_PLANE;
Pixel_Descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
Pixel_Descriptor.iPixelType = PFD_TYPE_RGBA;
Pixel_Descriptor.cColorBits = static_cast<BYTE>(Mode.Bits_Per_Pixel);
Pixel_Descriptor.cDepthBits = 24;
Pixel_Descriptor.cStencilBits = 8;
Pixel_Descriptor.cAlphaBits = Mode.Bits_Per_Pixel == 32 ? 8 : 0;
int Best_Format = ChoosePixelFormat(my_Device_Context, &Pixel_Descriptor);
if (0 == Best_Format)
throw std::runtime_error("Failed to find suitable pixel format");
PIXELFORMATDESCRIPTOR Actual_Format = {0};
Actual_Format.nSize = sizeof(Actual_Format);
Actual_Format.nVersion = 1;
DescribePixelFormat(my_Device_Context, Best_Format, sizeof(Actual_Format), &Actual_Format);
if (!SetPixelFormat(my_Device_Context, Best_Format, &Actual_Format))
throw std::runtime_error("Failed to set device pixel format");
my_GL_Context = wglCreateContext(my_Device_Context);
if (!my_GL_Context)
throw std::runtime_error("Failed to create OpenGL context");
wglMakeCurrent(my_Device_Context, my_GL_Context);
}
void Window::Destroy_Context()
{
if (my_GL_Context)
{
wglDeleteContext(my_GL_Context);
my_GL_Context = 0;
}
if (my_Device_Context)
{
ReleaseDC(my_Handle, my_Device_Context);
my_Device_Context = 0;
}
}
void Window::Switch_To_Fullscreen(const Video_Mode &Mode)
{
DEVMODE Device_Mode = {0};
Device_Mode.dmSize = sizeof(Device_Mode);
Device_Mode.dmPelsWidth = Mode.Width;
Device_Mode.dmPelsHeight = Mode.Height;
Device_Mode.dmBitsPerPel = Mode.Bits_Per_Pixel;
Device_Mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings(&Device_Mode, CDS_FULLSCREEN))
throw std::runtime_error("Failed to change to fullscreen mode");
SetWindowLong(my_Handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
SetWindowLong(my_Handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
SetWindowPos(my_Handle, HWND_TOP, 0, 0, Mode.Width, Mode.Height, SWP_FRAMECHANGED);
}
LRESULT CALLBACK Window::Window_Procedure(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_CREATE:
{
LONG This = reinterpret_cast<LONG>(reinterpret_cast<CREATESTRUCT *>(lParam)->lpCreateParams);
SetWindowLongPtr(Handle, GWLP_USERDATA, This);
return 0;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
default:
{
Window* Win = reinterpret_cast<Window *>(GetWindowLongPtr(Handle, GWLP_USERDATA));
if (Win)
return Win->Handle_Message(Handle, Message, wParam, lParam);
}
break;
}
return DefWindowProcW(Handle, Message, wParam, lParam);
}
#define Call_Listener(x)\
if (my_Listener) my_Listener->x
LRESULT Window::Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_SIZE:
Call_Listener(On_Resized(LOWORD(lParam), HIWORD(lParam)));
break;
case WM_CLOSE:
Call_Listener(On_Close());
break;
case WM_KEYDOWN:
Call_Listener(On_Key_Down(wParam));
break;
case WM_KEYUP:
Call_Listener(On_Key_Up(wParam));
break;
case WM_CHAR:
Call_Listener(On_Char(wParam));
break;
default:
return DefWindowProcW(Handle, Message, wParam, lParam);
break;
}
return 0;
}
void Window::Show()
{
if (my_Handle)
ShowWindow(my_Handle, SW_SHOW);
}
void Window::Hide()
{
if (my_Handle)
ShowWindow(my_Handle, SW_HIDE);
}
void Window::Handle_Events()
{
MSG Message = {0};
while (PeekMessageW(&Message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessageW(&Message);
}
}
void Window::Display()
{
if (my_Device_Context && my_GL_Context)
SwapBuffers(my_Device_Context);
}
void Window::Show_Cursor()
{
ShowCursor(TRUE);
}
void Window::Hide_Cursor()
{
ShowCursor(FALSE);
}
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -472,6 +472,19 @@ extern DECLSPEC size_t SDLCALL SDL_strlen(const char *string); ...@@ -472,6 +472,19 @@ extern DECLSPEC size_t SDLCALL SDL_strlen(const char *string);
extern DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t * string); extern DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t * string);
#endif #endif
#ifdef HAVE_WCSLCPY
#define SDL_wcslcpy wcslcpy
#else
extern DECLSPEC size_t SDLCALL SDL_wcslcpy(wchar_t *dst, const wchar_t *src, size_t maxlen);
#endif
#ifdef HAVE_WCSLCAT
#define SDL_wcslcat wcslcat
#else
extern DECLSPEC size_t SDLCALL SDL_wcslcat(wchar_t *dst, const wchar_t *src, size_t maxlen);
#endif
#ifdef HAVE_STRLCPY #ifdef HAVE_STRLCPY
#define SDL_strlcpy strlcpy #define SDL_strlcpy strlcpy
#else #else
...@@ -479,6 +492,9 @@ extern DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, ...@@ -479,6 +492,9 @@ extern DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src,
size_t maxlen); size_t maxlen);
#endif #endif
extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(char *dst, const char *src,
size_t dst_bytes);
#ifdef HAVE_STRLCAT #ifdef HAVE_STRLCAT
#define SDL_strlcat strlcat #define SDL_strlcat strlcat
#else #else
......
...@@ -778,7 +778,7 @@ SDL_SendKeyboardText(const char *text) ...@@ -778,7 +778,7 @@ SDL_SendKeyboardText(const char *text)
SDL_Event event; SDL_Event event;
event.text.type = SDL_TEXTINPUT; event.text.type = SDL_TEXTINPUT;
event.text.windowID = keyboard->focus ? keyboard->focus->id : 0; event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
SDL_strlcpy(event.text.text, text, SDL_arraysize(event.text.text)); SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
event.text.windowID = keyboard->focus ? keyboard->focus->id : 0; event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
posted = (SDL_PushEvent(&event) > 0); posted = (SDL_PushEvent(&event) > 0);
} }
...@@ -799,7 +799,7 @@ SDL_SendEditingText(const char *text, int start, int length) ...@@ -799,7 +799,7 @@ SDL_SendEditingText(const char *text, int start, int length)
event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
event.edit.start = start; event.edit.start = start;
event.edit.length = length; event.edit.length = length;
SDL_strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text)); SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
posted = (SDL_PushEvent(&event) > 0); posted = (SDL_PushEvent(&event) > 0);
} }
return (posted); return (posted);
......
...@@ -43,35 +43,35 @@ typedef struct ...@@ -43,35 +43,35 @@ typedef struct
} NDS_HapticData; } NDS_HapticData;
void void
NDS_EZF_OpenNorWrite() NDS_EZF_OpenNorWrite()
{ {
GBA_BUS[0x0FF0000] = 0xD200; GBA_BUS[0x0FF0000] = 0xD200;
GBA_BUS[0x0000000] = 0x1500; GBA_BUS[0x0000000] = 0x1500;
GBA_BUS[0x0010000] = 0xD200; GBA_BUS[0x0010000] = 0xD200;
GBA_BUS[0x0020000] = 0x1500; GBA_BUS[0x0020000] = 0x1500;
GBA_BUS[0x0E20000] = 0x1500; GBA_BUS[0x0E20000] = 0x1500;
GBA_BUS[0x0FE0000] = 0x1500; GBA_BUS[0x0FE0000] = 0x1500;
} void } void
NDS_EZF_CloseNorWrite() NDS_EZF_CloseNorWrite()
{ {
GBA_BUS[0x0FF0000] = 0xD200; GBA_BUS[0x0FF0000] = 0xD200;
GBA_BUS[0x0000000] = 0x1500; GBA_BUS[0x0000000] = 0x1500;
GBA_BUS[0x0010000] = 0xD200; GBA_BUS[0x0010000] = 0xD200;
GBA_BUS[0x0020000] = 0x1500; GBA_BUS[0x0020000] = 0x1500;
GBA_BUS[0x0E20000] = 0xD200; GBA_BUS[0x0E20000] = 0xD200;
GBA_BUS[0x0FE0000] = 0x1500; GBA_BUS[0x0FE0000] = 0x1500;
} }
void void
NDS_EZF_ChipReset() NDS_EZF_ChipReset()
{ {
GBA_BUS[0x0000] = 0x00F0; GBA_BUS[0x0000] = 0x00F0;
GBA_BUS[0x1000] = 0x00F0; GBA_BUS[0x1000] = 0x00F0;
} uint32 NDS_EZF_IsPresent() } uint32 NDS_EZF_IsPresent()
{ {
vuint16 id1, id2; vuint16 id1, id2;
NDS_EZF_OpenNorWrite(); NDS_EZF_OpenNorWrite();
...@@ -81,35 +81,35 @@ NDS_EZF_ChipReset() ...@@ -81,35 +81,35 @@ NDS_EZF_ChipReset()
GBA_BUS[0x1555] = 0x00AA; GBA_BUS[0x1555] = 0x00AA;
GBA_BUS[0x12AA] = 0x0055; GBA_BUS[0x12AA] = 0x0055;
GBA_BUS[0x1555] = 0x0090; GBA_BUS[0x1555] = 0x0090;
id1 = GBA_BUS[0x0001]; id1 = GBA_BUS[0x0001];
id2 = GBA_BUS[0x1001]; id2 = GBA_BUS[0x1001];
if ((id1 != 0x227E) || (id2 != 0x227E)) { if ((id1 != 0x227E) || (id2 != 0x227E)) {
NDS_EZF_CloseNorWrite(); NDS_EZF_CloseNorWrite();
return 0; return 0;
} }
id1 = GBA_BUS[0x000E]; id1 = GBA_BUS[0x000E];
id2 = GBA_BUS[0x100E]; id2 = GBA_BUS[0x100E];
NDS_EZF_CloseNorWrite(); NDS_EZF_CloseNorWrite();
if (id1 == 0x2218 && id2 == 0x2218) { if (id1 == 0x2218 && id2 == 0x2218) {
return 1; return 1;
} }
return 0; return 0;
} }
void void
NDS_EZF_SetShake(u8 pos) NDS_EZF_SetShake(u8 pos)
{ {
u16 data = ((pos % 3) | 0x00F0); u16 data = ((pos % 3) | 0x00F0);
GBA_BUS[0x0FF0000] = 0xD200; GBA_BUS[0x0FF0000] = 0xD200;
GBA_BUS[0x0000000] = 0x1500; GBA_BUS[0x0000000] = 0x1500;
GBA_BUS[0x0010000] = 0xD200; GBA_BUS[0x0010000] = 0xD200;
GBA_BUS[0x0020000] = 0x1500; GBA_BUS[0x0020000] = 0x1500;
GBA_BUS[0x0F10000] = data; GBA_BUS[0x0F10000] = data;
GBA_BUS[0x0FE0000] = 0x1500; GBA_BUS[0x0FE0000] = 0x1500;
GBA_BUS[0] = 0x0000; /* write any value for vibration. */ GBA_BUS[0] = 0x0000; /* write any value for vibration. */
GBA_BUS[0] = 0x0002; GBA_BUS[0] = 0x0002;
} }
static int static int
SDL_SYS_LogicError(void) SDL_SYS_LogicError(void)
......
...@@ -45,7 +45,7 @@ int ...@@ -45,7 +45,7 @@ int
SDL_SYS_JoystickInit(void) SDL_SYS_JoystickInit(void)
{ {
SDL_numjoysticks = 1; SDL_numjoysticks = 1;
return (1); return (1);
} }
/* Function to get the device-dependent name of a joystick */ /* Function to get the device-dependent name of a joystick */
...@@ -73,7 +73,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick) ...@@ -73,7 +73,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
return 0; return 0;
} }
/* Function to update the state of a joystick - called as a device poll. /* Function to update the state of a joystick - called as a device poll.
* This function shouldn't update the joystick structure directly, * This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events * but instead should call SDL_PrivateJoystick*() to deliver events
...@@ -84,8 +84,8 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) ...@@ -84,8 +84,8 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
{ {
u32 keysd, keysu; u32 keysd, keysu;
int magnitude = 16384; int magnitude = 16384;
/*scanKeys(); - this is done in PumpEvents, because touch uses it too */ /*scanKeys(); - this is done in PumpEvents, because touch uses it too */
keysd = keysDown(); keysd = keysDown();
keysu = keysUp(); keysu = keysUp();
...@@ -101,61 +101,61 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) ...@@ -101,61 +101,61 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
if ((keysd & KEY_RIGHT)) { if ((keysd & KEY_RIGHT)) {
SDL_PrivateJoystickAxis(joystick, 0, magnitude); SDL_PrivateJoystickAxis(joystick, 0, magnitude);
} }
if ((keysu & (KEY_UP | KEY_DOWN))) { if ((keysu & (KEY_UP | KEY_DOWN))) {
SDL_PrivateJoystickAxis(joystick, 1, 0); SDL_PrivateJoystickAxis(joystick, 1, 0);
} }
if ((keysu & (KEY_LEFT | KEY_RIGHT))) { if ((keysu & (KEY_LEFT | KEY_RIGHT))) {
SDL_PrivateJoystickAxis(joystick, 0, 0); SDL_PrivateJoystickAxis(joystick, 0, 0);
} }
if ((keysd & KEY_A)) { if ((keysd & KEY_A)) {
SDL_PrivateJoystickButton(joystick, 0, SDL_PRESSED); SDL_PrivateJoystickButton(joystick, 0, SDL_PRESSED);
} }
if ((keysd & KEY_B)) { if ((keysd & KEY_B)) {
SDL_PrivateJoystickButton(joystick, 1, SDL_PRESSED); SDL_PrivateJoystickButton(joystick, 1, SDL_PRESSED);
} }
if ((keysd & KEY_X)) { if ((keysd & KEY_X)) {
SDL_PrivateJoystickButton(joystick, 2, SDL_PRESSED); SDL_PrivateJoystickButton(joystick, 2, SDL_PRESSED);
} }
if ((keysd & KEY_Y)) { if ((keysd & KEY_Y)) {
SDL_PrivateJoystickButton(joystick, 3, SDL_PRESSED); SDL_PrivateJoystickButton(joystick, 3, SDL_PRESSED);
} }
if ((keysd & KEY_L)) { if ((keysd & KEY_L)) {
SDL_PrivateJoystickButton(joystick, 4, SDL_PRESSED); SDL_PrivateJoystickButton(joystick, 4, SDL_PRESSED);
} }
if ((keysd & KEY_R)) { if ((keysd & KEY_R)) {
SDL_PrivateJoystickButton(joystick, 5, SDL_PRESSED); SDL_PrivateJoystickButton(joystick, 5, SDL_PRESSED);
} }
if ((keysd & KEY_SELECT)) { if ((keysd & KEY_SELECT)) {
SDL_PrivateJoystickButton(joystick, 6, SDL_PRESSED); SDL_PrivateJoystickButton(joystick, 6, SDL_PRESSED);
} }
if ((keysd & KEY_START)) { if ((keysd & KEY_START)) {
SDL_PrivateJoystickButton(joystick, 7, SDL_PRESSED); SDL_PrivateJoystickButton(joystick, 7, SDL_PRESSED);
} }
if ((keysu & KEY_A)) { if ((keysu & KEY_A)) {
SDL_PrivateJoystickButton(joystick, 0, SDL_RELEASED); SDL_PrivateJoystickButton(joystick, 0, SDL_RELEASED);
} }
if ((keysu & KEY_B)) { if ((keysu & KEY_B)) {
SDL_PrivateJoystickButton(joystick, 1, SDL_RELEASED); SDL_PrivateJoystickButton(joystick, 1, SDL_RELEASED);
} }
if ((keysu & KEY_X)) { if ((keysu & KEY_X)) {
SDL_PrivateJoystickButton(joystick, 2, SDL_RELEASED); SDL_PrivateJoystickButton(joystick, 2, SDL_RELEASED);
} }
if ((keysu & KEY_Y)) { if ((keysu & KEY_Y)) {
SDL_PrivateJoystickButton(joystick, 3, SDL_RELEASED); SDL_PrivateJoystickButton(joystick, 3, SDL_RELEASED);
} }
if ((keysu & KEY_L)) { if ((keysu & KEY_L)) {
SDL_PrivateJoystickButton(joystick, 4, SDL_RELEASED); SDL_PrivateJoystickButton(joystick, 4, SDL_RELEASED);
} }
if ((keysu & KEY_R)) { if ((keysu & KEY_R)) {
SDL_PrivateJoystickButton(joystick, 5, SDL_RELEASED); SDL_PrivateJoystickButton(joystick, 5, SDL_RELEASED);
} }
if ((keysu & KEY_SELECT)) { if ((keysu & KEY_SELECT)) {
SDL_PrivateJoystickButton(joystick, 6, SDL_RELEASED); SDL_PrivateJoystickButton(joystick, 6, SDL_RELEASED);
} }
if ((keysu & KEY_START)) { if ((keysu & KEY_START)) {
SDL_PrivateJoystickButton(joystick, 7, SDL_RELEASED); SDL_PrivateJoystickButton(joystick, 7, SDL_RELEASED);
} }
} }
/* Function to close a joystick after use */ /* Function to close a joystick after use */
void void
......
...@@ -29,6 +29,21 @@ ...@@ -29,6 +29,21 @@
#define SDL_isupperhex(X) (((X) >= 'A') && ((X) <= 'F')) #define SDL_isupperhex(X) (((X) >= 'A') && ((X) <= 'F'))
#define SDL_islowerhex(X) (((X) >= 'a') && ((X) <= 'f')) #define SDL_islowerhex(X) (((X) >= 'a') && ((X) <= 'f'))
#define UTF8_IsLeadByte(c) ((c) >= 0xC0 && (c) <= 0xF4)
#define UTF8_IsTrailingByte(c) ((c) >= 0x80 && (c) <= 0xBF)
int UTF8_TrailingBytes(unsigned char c)
{
if (c >= 0xC0 && c<= 0xDF)
return 1;
else if (c >= 0xE0 && c <= 0xEF)
return 2;
else if (c >= 0xF0 && c <= 0xF4)
return 3;
else
return 0;
}
#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL) #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL)
static size_t static size_t
SDL_ScanLong(const char *text, int radix, long *valuep) SDL_ScanLong(const char *text, int radix, long *valuep)
...@@ -348,6 +363,33 @@ SDL_wcslen(const wchar_t * string) ...@@ -348,6 +363,33 @@ SDL_wcslen(const wchar_t * string)
} }
#endif #endif
#ifndef HAVE_WCSLCPY
size_t
SDL_wcslcpy(wchar_t *dst, const wchar_t *src, size_t maxlen)
{
size_t srclen = SDL_wcslen(src);
if (maxlen > 0) {
size_t len = SDL_min(srclen, maxlen - 1);
SDL_memcpy(dst, src, len * sizeof(wchar_t));
dst[len] = '\0';
}
return srclen;
}
#endif
#ifndef HAVE_WCSLCAT
size_t
SDL_wcslcat(wchar_t *dst, const wchar_t *src, size_t maxlen)
{
size_t dstlen = SDL_wcslen(dst);
size_t srclen = SDL_wcslen(src);
if (dstlen < maxlen) {
SDL_wcslcpy(dst + dstlen, src, maxlen - dstlen);
}
return dstlen + srclen;
}
#endif
#ifndef HAVE_STRLCPY #ifndef HAVE_STRLCPY
size_t size_t
SDL_strlcpy(char *dst, const char *src, size_t maxlen) SDL_strlcpy(char *dst, const char *src, size_t maxlen)
...@@ -362,6 +404,38 @@ SDL_strlcpy(char *dst, const char *src, size_t maxlen) ...@@ -362,6 +404,38 @@ SDL_strlcpy(char *dst, const char *src, size_t maxlen)
} }
#endif #endif
size_t SDL_utf8strlcpy(char *dst, const char *src, size_t dst_bytes)
{
size_t src_bytes = SDL_strlen(src);
size_t bytes = SDL_min(src_bytes, dst_bytes - 1);
int i = 0;
char trailing_bytes = 0;
if (bytes)
{
unsigned char c = (unsigned char)src[bytes - 1];
if (UTF8_IsLeadByte(c))
--bytes;
else if (UTF8_IsTrailingByte(c))
{
for (i = bytes - 1; i != 0; --i)
{
c = (unsigned char)src[i];
trailing_bytes = UTF8_TrailingBytes(c);
if (trailing_bytes)
{
if (bytes - i != trailing_bytes + 1)
bytes = i;
break;
}
}
}
SDL_memcpy(dst, src, bytes);
}
dst[bytes] = '\0';
return bytes;
}
#ifndef HAVE_STRLCAT #ifndef HAVE_STRLCAT
size_t size_t
SDL_strlcat(char *dst, const char *src, size_t maxlen) SDL_strlcat(char *dst, const char *src, size_t maxlen)
......
...@@ -139,6 +139,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) ...@@ -139,6 +139,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
} }
#endif #endif
if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
return 0;
switch (msg) { switch (msg) {
...@@ -605,7 +607,7 @@ SDL_RegisterApp(char *name, Uint32 style, void *hInst) ...@@ -605,7 +607,7 @@ SDL_RegisterApp(char *name, Uint32 style, void *hInst)
class.hbrBackground = NULL; class.hbrBackground = NULL;
class.hInstance = SDL_Instance; class.hInstance = SDL_Instance;
class.style = SDL_Appstyle; class.style = SDL_Appstyle;
class.lpfnWndProc = DefWindowProc; class.lpfnWndProc = WIN_WindowProc;
class.cbWndExtra = 0; class.cbWndExtra = 0;
class.cbClsExtra = 0; class.cbClsExtra = 0;
if (!RegisterClass(&class)) { if (!RegisterClass(&class)) {
......
This diff is collapsed.
...@@ -31,6 +31,12 @@ extern void WIN_InitKeyboard(_THIS); ...@@ -31,6 +31,12 @@ extern void WIN_InitKeyboard(_THIS);
extern void WIN_UpdateKeymap(void); extern void WIN_UpdateKeymap(void);
extern void WIN_QuitKeyboard(_THIS); extern void WIN_QuitKeyboard(_THIS);
extern void WIN_StartTextInput(_THIS);
extern void WIN_StopTextInput(_THIS);
extern void WIN_SetTextInputRect(_THIS, SDL_Rect *rect);
extern SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata);
#endif /* _SDL_win32keyboard_h */ #endif /* _SDL_win32keyboard_h */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
...@@ -191,6 +191,9 @@ WIN_CreateDevice(int devindex) ...@@ -191,6 +191,9 @@ WIN_CreateDevice(int devindex)
device->GL_SwapWindow = WIN_GL_SwapWindow; device->GL_SwapWindow = WIN_GL_SwapWindow;
device->GL_DeleteContext = WIN_GL_DeleteContext; device->GL_DeleteContext = WIN_GL_DeleteContext;
#endif #endif
device->StartTextInput = WIN_StartTextInput;
device->StopTextInput = WIN_StopTextInput;
device->SetTextInputRect = WIN_SetTextInputRect;
device->SetClipboardText = WIN_SetClipboardText; device->SetClipboardText = WIN_SetClipboardText;
device->GetClipboardText = WIN_GetClipboardText; device->GetClipboardText = WIN_GetClipboardText;
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#include <windows.h> #include <windows.h>
#include <msctf.h>
#if SDL_VIDEO_RENDER_D3D #if SDL_VIDEO_RENDER_D3D
//#include <d3d9.h> //#include <d3d9.h>
#define D3D_DEBUG_INFO #define D3D_DEBUG_INFO
...@@ -62,6 +64,7 @@ ...@@ -62,6 +64,7 @@
#include "SDL_win32mouse.h" #include "SDL_win32mouse.h"
#include "SDL_win32opengl.h" #include "SDL_win32opengl.h"
#include "SDL_win32window.h" #include "SDL_win32window.h"
#include "SDL_events.h"
#ifdef UNICODE #ifdef UNICODE
#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UCS-2", (char *)S, (SDL_wcslen(S)+1)*sizeof(WCHAR)) #define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UCS-2", (char *)S, (SDL_wcslen(S)+1)*sizeof(WCHAR))
...@@ -77,6 +80,37 @@ enum { RENDER_NONE, RENDER_D3D, RENDER_DDRAW, RENDER_GDI, RENDER_GAPI, RENDER_RA ...@@ -77,6 +80,37 @@ enum { RENDER_NONE, RENDER_D3D, RENDER_DDRAW, RENDER_GDI, RENDER_GAPI, RENDER_RA
typedef BOOL (*PFNSHFullScreen)(HWND, DWORD); typedef BOOL (*PFNSHFullScreen)(HWND, DWORD);
typedef void (*PFCoordTransform)(SDL_Window*, POINT*); typedef void (*PFCoordTransform)(SDL_Window*, POINT*);
typedef struct
{
void **lpVtbl;
int refcount;
void *data;
} TSFSink;
// Definition from Win98DDK version of IMM.H
typedef struct tagINPUTCONTEXT2 {
HWND hWnd;
BOOL fOpen;
POINT ptStatusWndPos;
POINT ptSoftKbdPos;
DWORD fdwConversion;
DWORD fdwSentence;
union {
LOGFONTA A;
LOGFONTW W;
} lfFont;
COMPOSITIONFORM cfCompForm;
CANDIDATEFORM cfCandForm[4];
HIMCC hCompStr;
HIMCC hCandInfo;
HIMCC hGuideLine;
HIMCC hPrivate;
DWORD dwNumMsgBuf;
HIMCC hMsgBuf;
DWORD fdwInit;
DWORD dwReserve[3];
} INPUTCONTEXT2, *PINPUTCONTEXT2, NEAR *NPINPUTCONTEXT2, FAR *LPINPUTCONTEXT2;
/* Private display data */ /* Private display data */
typedef struct SDL_VideoData typedef struct SDL_VideoData
...@@ -97,9 +131,39 @@ typedef struct SDL_VideoData ...@@ -97,9 +131,39 @@ typedef struct SDL_VideoData
PFCoordTransform CoordTransform; PFCoordTransform CoordTransform;
#endif #endif
const SDL_scancode *key_layout;
DWORD clipboard_count; DWORD clipboard_count;
const SDL_scancode *key_layout; SDL_bool ime_com_initialized;
struct ITfThreadMgr *ime_threadmgr;
SDL_bool ime_initialized;
SDL_bool ime_enabled;
SDL_bool ime_available;
HWND ime_hwnd_main;
HWND ime_hwnd_current;
HIMC ime_himc;
WCHAR ime_composition[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
WCHAR ime_readingstring[16];
int ime_cursor;
HKL ime_hkl;
HMODULE ime_himm32;
UINT (WINAPI *GetReadingString)(HIMC himc, UINT uReadingBufLen, LPWSTR lpwReadingBuf, PINT pnErrorIndex, BOOL *pfIsVertical, PUINT puMaxReadingLen);
BOOL (WINAPI *ShowReadingWindow)(HIMC himc, BOOL bShow);
LPINPUTCONTEXT2 (WINAPI *ImmLockIMC)(HIMC himc);
BOOL (WINAPI *ImmUnlockIMC)(HIMC himc);
LPVOID (WINAPI *ImmLockIMCC)(HIMCC himcc);
BOOL (WINAPI *ImmUnlockIMCC)(HIMCC himcc);
SDL_bool ime_uiless;
struct ITfThreadMgrEx *ime_threadmgrex;
DWORD ime_uielemsinkcookie;
DWORD ime_alpnsinkcookie;
DWORD ime_openmodesinkcookie;
DWORD ime_convmodesinkcookie;
TSFSink *ime_uielemsink;
TSFSink *ime_ippasink;
} SDL_VideoData; } SDL_VideoData;
#endif /* _SDL_win32video_h */ #endif /* _SDL_win32video_h */
......
...@@ -77,10 +77,12 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created) ...@@ -77,10 +77,12 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
/* Set up the window proc function */ /* Set up the window proc function */
data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC); data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
if (data->wndproc == DefWindowProc) { if (data->wndproc == WIN_WindowProc) {
data->wndproc = NULL; data->wndproc = NULL;
} }
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc); else {
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
}
/* Fill in the SDL window with the window data */ /* Fill in the SDL window with the window data */
{ {
......
...@@ -25,7 +25,49 @@ TTF_Font *font; ...@@ -25,7 +25,49 @@ TTF_Font *font;
SDL_Rect textRect, markedRect; SDL_Rect textRect, markedRect;
Uint32 lineColor, backColor; Uint32 lineColor, backColor;
SDL_Color textColor = { 0, 0, 0 }; SDL_Color textColor = { 0, 0, 0 };
char text[MAX_TEXT_LENGTH], *markedText; char text[MAX_TEXT_LENGTH], markedText[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
int cursor = 0;
size_t utf8_length(unsigned char c)
{
c = (unsigned char)(0xff & c);
if (c < 0x80)
return 1;
else if ((c >> 5) ==0x6)
return 2;
else if ((c >> 4) == 0xe)
return 3;
else if ((c >> 3) == 0x1e)
return 4;
else
return 0;
}
char *utf8_next(char *p)
{
size_t len = utf8_length(*p);
size_t i = 0;
if (!len)
return 0;
for (; i < len; ++i)
{
++p;
if (!*p)
return 0;
}
return p;
}
char *utf8_advance(char *p, size_t distance)
{
size_t i = 0;
for (; i < distance && p; ++i)
{
p = utf8_next(p);
}
return p;
}
void usage() void usage()
{ {
...@@ -124,7 +166,7 @@ void InitInput() ...@@ -124,7 +166,7 @@ void InitInput()
text[0] = 0; text[0] = 0;
markedRect = textRect; markedRect = textRect;
markedText = NULL; markedText[0] = 0;
SDL_StartTextInput(); SDL_StartTextInput();
} }
...@@ -180,9 +222,22 @@ void Redraw() ...@@ -180,9 +222,22 @@ void Redraw()
cursorRect.h = h; cursorRect.h = h;
SDL_FillRect(screen, &markedRect, backColor); SDL_FillRect(screen, &markedRect, backColor);
if (markedText) if (markedText[0])
{ {
#ifdef HAVE_SDL_TTF #ifdef HAVE_SDL_TTF
if (cursor)
{
char *p = utf8_advance(markedText, cursor);
char c = 0;
if (!p)
p = &markedText[strlen(markedText)];
c = *p;
*p = 0;
TTF_SizeUTF8(font, markedText, &w, 0);
cursorRect.x += w;
*p = c;
}
RenderText(screen, font, markedText, markedRect.x, markedRect.y, textColor); RenderText(screen, font, markedText, markedRect.x, markedRect.y, textColor);
TTF_SizeUTF8(font, markedText, &w, &h); TTF_SizeUTF8(font, markedText, &w, &h);
#endif #endif
...@@ -192,8 +247,6 @@ void Redraw() ...@@ -192,8 +247,6 @@ void Redraw()
underlineRect.h = 2; underlineRect.h = 2;
underlineRect.w = w; underlineRect.w = w;
cursorRect.x += w + 1;
SDL_FillRect(screen, &underlineRect, lineColor); SDL_FillRect(screen, &underlineRect, lineColor);
} }
...@@ -295,13 +348,13 @@ int main(int argc, char *argv[]) ...@@ -295,13 +348,13 @@ int main(int argc, char *argv[])
fprintf(stderr, "Keyboard: text input \"%s\"\n", event.text.text); fprintf(stderr, "Keyboard: text input \"%s\"\n", event.text.text);
if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text)) if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text))
SDL_strlcpy(text + SDL_strlen(text), event.text.text, sizeof(text)); SDL_strlcat(text, event.text.text, sizeof(text));
fprintf(stderr, "text inputed: %s\n", text); fprintf(stderr, "text inputed: %s\n", text);
// After text inputed, we can clear up markedText because it // After text inputed, we can clear up markedText because it
// is committed // is committed
markedText = NULL; markedText[0] = 0;
Redraw(); Redraw();
break; break;
...@@ -309,7 +362,8 @@ int main(int argc, char *argv[]) ...@@ -309,7 +362,8 @@ int main(int argc, char *argv[])
fprintf(stderr, "text editing \"%s\", selected range (%d, %d)\n", fprintf(stderr, "text editing \"%s\", selected range (%d, %d)\n",
event.edit.text, event.edit.start, event.edit.length); event.edit.text, event.edit.start, event.edit.length);
markedText = event.edit.text; strcpy(markedText, event.edit.text);
cursor = event.edit.start;
Redraw(); Redraw();
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment