No project download is available. This is a code snippet and not a complete project.
These filters are from XSquawkBox – they are tested and in a shipping plugin.
These filters take the form of a widget function and a helper function that attaches them – a simple way to specialize widget behavior.
Protecting from null characters
Older versions of the SDK sometimes sent null characters to text fields, crashing the sim. This small snippet protects a widget from this. This is unneeded for newer versions of X-Plane.
static int WidgetFunc_EatNullChars(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
long inParam1,
long inParam2)
{
if (inMessage == xpMsg_KeyPress)
{
char theChar = KEY_CHAR(inParam1);
if (theChar == 0)
return 1; // Eat the null char!
}
return 0;
}
void ProtectTextWidget(XPWidgetID inWidgetID)
{
XPAddWidgetCallback(inWidgetID, WidgetFunc_EatNullChars);
}
Cut Copy and Paste with the OS
This attaches control V, C, and X as cut/copy/patste. It works on Mac and Windows.
bool XSBGetTextFromClipboard(std::string& outText)
{
#if IBM
HGLOBAL hglb;
LPTSTR lptstr;
bool retVal = false;
static XPLMDataRef hwndDataRef = XPLMFindDataRef("sim/operation/windows/system_window");
HWND hwndMain = (HWND) XPLMGetDatai(hwndDataRef);
if (!IsClipboardFormatAvailable(CF_TEXT))
return false;
if (!OpenClipboard(hwndMain))
return false;
hglb = GetClipboardData(CF_TEXT);
if (hglb != NULL)
{
lptstr = (LPSTR)GlobalLock(hglb);
if (lptstr != NULL)
{
outText = lptstr;
GlobalUnlock(hglb);
retVal = true;
}
}
CloseClipboard();
return retVal;
#endif
#if APL
ScrapRef scrap;
if (::GetCurrentScrap(&scrap) != noErr)
return false;
SInt32 byteCount = 0;
OSStatus status = ::GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &byteCount);
if (status != noErr)
return false;
outText.resize(byteCount);
return (::GetScrapFlavorData(scrap, kScrapFlavorTypeText, &byteCount, &*outText.begin() ) == noErr);
#endif
}
bool XSBSetTextToClipboard(const std::string& inText)
{
#if IBM
LPTSTR lptstrCopy;
HGLOBAL hglbCopy;
static XPLMDataRef hwndDataRef = XPLMFindDataRef("sim/operation/windows/system_window");
HWND hwndMain = (HWND) XPLMGetDatai(hwndDataRef);
if (!OpenClipboard(hwndMain))
return false;
EmptyClipboard();
hglbCopy = GlobalAlloc(GMEM_MOVEABLE, sizeof(TCHAR) * (inText.length() + 1));
if (hglbCopy == NULL)
{
CloseClipboard();
return false;
}
lptstrCopy = (LPSTR)GlobalLock(hglbCopy);
strcpy(lptstrCopy, inText.c_str());
GlobalUnlock(hglbCopy);
SetClipboardData(CF_TEXT, hglbCopy);
CloseClipboard();
return true;
#endif
#if APL
ScrapRef scrap;
if (::ClearCurrentScrap() != noErr) return false;
if (::GetCurrentScrap(&scrap) != noErr) return false;
return ::PutScrapFlavor( scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone, inText.size(), &*inText.begin()) == noErr;
#endif
}
static int WidgetFunc_CutCopyPaste(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
long inParam1,
long inParam2)
{
if (inMessage == xpMsg_KeyPress)
{
char theChar = KEY_VKEY(inParam1);
XPLMKeyFlags flags = KEY_FLAGS(inParam1);
if ((flags & (xplm_DownFlag + xplm_ControlFlag)) == (xplm_DownFlag + xplm_ControlFlag))
{
long selStart = XPGetWidgetProperty(inWidget, xpProperty_EditFieldSelStart, NULL);
long selEnd = XPGetWidgetProperty(inWidget, xpProperty_EditFieldSelEnd, NULL);
long strLen = XPGetWidgetDescriptor(inWidget, NULL, 0);
std::string txt;
txt.resize(strLen);
XPGetWidgetDescriptor(inWidget, &*txt.begin(), txt.size()+1);
if (theChar == XPLM_VK_V)
{
std::string scrap;
if (XSBGetTextFromClipboard(scrap) && !scrap.empty())
{
if ((selEnd > selStart) && (selStart >= 0) && (selEnd <= strLen))
{
txt.replace(selStart, selEnd - selStart, scrap);
XPSetWidgetDescriptor(inWidget, txt.c_str());
XPSetWidgetProperty(inWidget, xpProperty_EditFieldSelStart, selStart + scrap.size());
XPSetWidgetProperty(inWidget, xpProperty_EditFieldSelEnd, selStart + scrap.size());
} else if ((selStart >= 0) && (selStart <= strLen)) {
txt.insert(selStart, scrap);
XPSetWidgetDescriptor(inWidget, txt.c_str());
XPSetWidgetProperty(inWidget, xpProperty_EditFieldSelStart, selStart + scrap.size());
XPSetWidgetProperty(inWidget, xpProperty_EditFieldSelEnd, selStart + scrap.size());
}
}
return 1;
}
if ((theChar == XPLM_VK_C) || (theChar == XPLM_VK_X))
{
if ((selStart >= 0) && (selStart < selEnd) && (selEnd <= strLen))
{
std::string scrap = txt.substr(selStart, selEnd - selStart);
if (XSBSetTextToClipboard(scrap) && (theChar == XPLM_VK_X))
{
txt.erase(selStart, selEnd - selStart);
XPSetWidgetDescriptor(inWidget, txt.c_str());
XPSetWidgetProperty(inWidget, xpProperty_EditFieldSelEnd, selStart);
}
}
return 1;
}
}
}
return 0;
}
void AttachCutCopyPaste(XPWidgetID inWidget)
{
XPAddWidgetCallback(inWidget, WidgetFunc_CutCopyPaste);
}