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); }