spiegel-keyman/windows/src/engine/keyman32/addins.cpp
2020-10-02 14:54:43 +10:00

263 lines
8 KiB
C++

/*
Name: addins
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 14 Jun 2008
Modified Date: 14 May 2010
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 14 Jun 2008 - mcdurdin - I1488 - Fix registry handle leak
11 Mar 2009 - mcdurdin - I1894 - Fix threading bugs introduced in I1888
11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
12 Mar 2010 - mcdurdin - I934 - x64 - Complete
12 Mar 2010 - mcdurdin - I2229 - Remove hints and warnings
04 May 2010 - mcdurdin - I2351 - Robustness - verify _td return value
14 May 2010 - mcdurdin - I2374 - Fix crash in some situations
*/
#include "pch.h"
void Addin_Release()
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addin_Release: ENTER [%d]", nAddins);
if(_td->Addins)
{
for(int i = 0; i < _td->nAddins; i++)
if(_td->Addins[i].hAddin)
{
if(_td->Addins[i].Uninitialise) (*_td->Addins[i].Uninitialise)();
FreeLibrary(_td->Addins[i].hAddin);
}
delete[] _td->Addins;
}
_td->Addins = NULL;
_td->nAddins = 0;
_td->CurrentAddin = -1;
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addin_Release: EXIT");
}
void ReadAddins(HKEY hkey)
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: ReadAddins: ENTER");
RegistryReadOnly *reg = new RegistryReadOnly(hkey);
if(reg->OpenKeyReadOnly(hkey == HKEY_CURRENT_USER ? REGSZ_KeymanAddinsCU : REGSZ_KeymanAddinsLM))
{
int n = _td->nAddins;
char buf[128];
while(reg->GetValueNames(buf, 128, n))
{
Addin *a = new Addin[n+1];
if(_td->Addins)
{
memcpy(a, _td->Addins, n * sizeof(Addin));
delete[] _td->Addins;
}
_td->Addins = a;
_td->Addins[n].hAddin = 0;
_td->Addins[n].FocusChanged = NULL;
_td->Addins[n].Initialise = NULL;
_td->Addins[n].OutputBackspace = NULL;
_td->Addins[n].OutputChar = NULL;
_td->Addins[n].Uninitialise = NULL;
_td->Addins[n].ShouldProcess = NULL;
strcpy(_td->Addins[n].ClassName, buf);
reg->ReadString(buf, _td->Addins[n].AddinName, 260);
_td->Addins[n].Application[0] = 0;
n++;
}
_td->nAddins = n;
}
delete reg;
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: ReadAddins: EXIT");
}
void Addin_Refresh()
{
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addin_Refresh: ENTER");
Addin_Release();
ReadAddins(HKEY_CURRENT_USER);
ReadAddins(HKEY_LOCAL_MACHINE);
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addin_Refresh: EXIT");
}
BOOL LoadAddin()
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return FALSE;
if(_td->CurrentAddin == -1) return FALSE;
Addin *a = &_td->Addins[_td->CurrentAddin];
if(!a->hAddin)
{
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: LoadAddin: ENTER");
a->hAddin = LoadLibrary(a->AddinName);
if(!a->hAddin)
{
a->hAddin = 0;
a->ClassName[0] = 0; // prevent add-in attempting to load again
_td->CurrenthWnd = 0;
_td->CurrentAddin = -1;
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: LoadAddin: EXIT - FALSE - LoadLibrary");
return FALSE;
}
a->OutputBackspace = (PKeymanOutputBackspace) GetProcAddress(a->hAddin, "KeymanOutputBackspace");
a->OutputChar = (PKeymanOutputChar) GetProcAddress(a->hAddin, "KeymanOutputChar");
a->FocusChanged = (PKeymanFocusChanged) GetProcAddress(a->hAddin, "KeymanFocusChanged");
a->ShouldProcess = (PKeymanShouldProcess) GetProcAddress(a->hAddin, "KeymanShouldProcess");
a->Initialise = (PKeymanInit) GetProcAddress(a->hAddin, "KeymanInitialise");
a->Uninitialise = (PKeymanInit) GetProcAddress(a->hAddin, "KeymanUninitialise");
if(a->Initialise && !(*a->Initialise)())
{
FreeLibrary(a->hAddin);
a->hAddin = 0;
a->ClassName[0] = 0;
_td->CurrenthWnd = 0;
_td->CurrentAddin = -1;
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: LoadAddin: EXIT - FALSE - Initialise");
return FALSE;
}
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: LoadAddin: EXIT - TRUE - Loaded");
}
return TRUE;
}
BOOL Addin_ShouldProcessUnichar(HWND hwnd)
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return FALSE;
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ShouldProcessUnichar: ENTER");
_td->CurrenthWnd = hwnd;
GetClassName(hwnd, _td->CurrentClassName, 128);
if(_td->CurrentAddin >= 0 && !_strcmpi(_td->CurrentClassName, _td->Addins[_td->CurrentAddin].ClassName))
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ShouldProcessUnichar: EXIT - TRUE - CurrentAddin okay");
return TRUE;
}
for(int i = 0; i < _td->nAddins; i++)
if(!_strcmpi(_td->CurrentClassName, _td->Addins[i].ClassName))
{
_td->CurrentAddin = i;
if(!LoadAddin())
{
_td->CurrentAddin = -1;
_td->Addins[i].ClassName[0] = 0; // prevent add-in attempting to load again
}
else if(_td->Addins[i].ShouldProcess && !(*_td->Addins[i].ShouldProcess)(hwnd))
_td->CurrentAddin = -1;
else
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ShouldProcessUnichar: EXIT - TRUE - FoundAddin");
return TRUE;
}
}
_td->CurrentAddin = -1;
_td->CurrenthWnd = 0;
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ShouldProcessUnichar: EXIT - FALSE");
return FALSE;
}
BOOL Addin_ProcessUnichar(HWND hwnd, DWORD chr)
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return FALSE;
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: ENTER");
if(_td->CurrenthWnd != hwnd)
if(!Addin_ShouldProcessUnichar(hwnd))
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: EXIT - FALSE - Addin_ShouldProcessUnichar");
return FALSE;
}
if(!LoadAddin())
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: EXIT - FALSE - !LoadAddin)");
return FALSE;
}
if(!_td->Addins[_td->CurrentAddin].OutputChar)
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: EXIT - FALSE !OutputChar");
return FALSE;
}
BOOL b = (*_td->Addins[_td->CurrentAddin].OutputChar)(hwnd, chr);
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: EXIT (b) == %d", b);
return b;
}
BOOL Addin_ProcessBackspace(HWND hwnd)
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return FALSE;
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: ENTER");
if(_td->CurrenthWnd != hwnd)
if(!Addin_ShouldProcessUnichar(hwnd))
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: EXIT - !ShouldProcess");
return FALSE;
}
if(!LoadAddin())
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: EXIT - !LoadAddin");
return FALSE;
}
if(!_td->Addins[_td->CurrentAddin].OutputBackspace)
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: EXIT - !OutputBackspace");
return FALSE;
}
BOOL b = (*_td->Addins[_td->CurrentAddin].OutputBackspace)(hwnd);
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: EXIT - (b) = %d", b);
return b;
}
void Addin_FocusChanged(HWND hwnd)
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: ENTER");
if(_td->CurrenthWnd != hwnd)
if(!Addin_ShouldProcessUnichar(hwnd))
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: EXIT - !ShouldProcess");
return;
}
if(!LoadAddin())
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: EXIT - !LoadAddin");
return;
}
// Addin variables must be valid now
if(!_td->Addins[_td->CurrentAddin].FocusChanged)
{
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: EXIT - !FocusChanged");
return;
}
(*_td->Addins[_td->CurrentAddin].FocusChanged)();
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: EXIT");
}