ResultType Clipboard::Set(LPCTSTR aBuf, UINT_PTR aLength) // Returns OK or FAIL. { // It was already open for writing from a prior call. Return failure because callers that do this // are probably handling things wrong: if (IsReadyForWrite()) return FAIL; if (!aBuf) { aBuf = _T(""); aLength = 0; } else if (aLength == UINT_MAX) // Caller wants us to determine the length. aLength = (UINT)_tcslen(aBuf); if (aLength) { if (!PrepareForWrite(aLength + 1)) return FAIL; // It already displayed the error. tcslcpy(mClipMemNewLocked, aBuf, aLength + 1); // Copy only a substring, if aLength specifies such. } // else just do the below to empty the clipboard, which is different than setting // the clipboard equal to the empty string: it's not truly empty then, as reported // by IsClipboardFormatAvailable(CF_TEXT) -- and we want to be able to make it truly // empty for use with functions such as ClipWait: return Commit(); // It will display any errors. }
LPTSTR Clipboard::PrepareForWrite(size_t aAllocSize) { if (!aAllocSize) return NULL; // Caller should ensure that size is at least 1, i.e. room for the zero terminator. if (IsReadyForWrite()) // It was already prepared due to a prior call. Currently, the most useful thing to do // here is return the memory area that's already been reserved: return mClipMemNewLocked; // Note: I think GMEM_DDESHARE is recommended in addition to the usual GMEM_MOVEABLE: // UPDATE: MSDN: "The following values are obsolete, but are provided for compatibility // with 16-bit Windows. They are ignored.": GMEM_DDESHARE if ( !(mClipMemNew = GlobalAlloc(GMEM_MOVEABLE, aAllocSize * sizeof(TCHAR))) ) { g_script.ScriptError(_T("GlobalAlloc")); // Short error message since so rare. return NULL; } if ( !(mClipMemNewLocked = (LPTSTR)GlobalLock(mClipMemNew)) ) { mClipMemNew = GlobalFree(mClipMemNew); // This keeps mClipMemNew in sync with its state. g_script.ScriptError(_T("GlobalLock")); // Short error message since so rare. return NULL; } mCapacity = (UINT)aAllocSize; // Keep mCapacity in sync with the state of mClipMemNewLocked. *mClipMemNewLocked = '\0'; // Init for caller. return mClipMemNewLocked; // The caller can now write to this mem. }
ResultType Clipboard::Set(LPCTSTR aBuf, UINT_PTR aLength) //, bool aTrimIt) // Returns OK or FAIL. { // It was already open for writing from a prior call. Return failure because callers that do this // are probably handling things wrong: if (IsReadyForWrite()) return FAIL; if (!aBuf) { aBuf = _T(""); aLength = 0; } else if (aLength == UINT_MAX) // Caller wants us to determine the length. aLength = (UINT)_tcslen(aBuf); if (aLength) { if (!PrepareForWrite(aLength + 1)) return FAIL; // It already displayed the error. tcslcpy(mClipMemNewLocked, aBuf, aLength + 1); // Copy only a substring, if aLength specifies such. // Only trim when the caller told us to, rather than always if g_script.mIsAutoIt2 // is true, since AutoIt2 doesn't always trim things (e.g. FileReadLine probably // does not trim the line that was read into its output var). UPDATE: This is // no longer needed because I think AutoIt2 only auto-trims when SetEnv is used: //if (aTrimIt) // trim(mClipMemNewLocked); } // else just do the below to empty the clipboard, which is different than setting // the clipboard equal to the empty string: it's not truly empty then, as reported // by IsClipboardFormatAvailable(CF_TEXT) -- and we want to be able to make it truly // empty for use with functions such as ClipWait: return Commit(); // It will display any errors. }