| 42 | } |
| 43 | |
| 44 | HDDEDATA CALLBACK PDFBridgeSumatra::DdeCallback( |
| 45 | UINT uType, // Transaction type. |
| 46 | UINT uFmt, // Clipboard data format. |
| 47 | HCONV hconv, // Handle to the conversation. |
| 48 | HSZ hsz1, // Handle to a string. |
| 49 | HSZ hsz2, // Handle to a string. |
| 50 | HDDEDATA hdata, // Handle to a global memory object. |
| 51 | ULONG_PTR dwData1, // Transaction-specific data. |
| 52 | ULONG_PTR dwData2) { // Transaction-specific data. |
| 53 | SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "PDFBridgeSumatra DdeCallback, uType=%d", uType); |
| 54 | |
| 55 | |
| 56 | assert(PDFBridgeSumatra::instance != nullptr); |
| 57 | PDFBridgeSumatra &pdfBridgeSumatra = *PDFBridgeSumatra::instance; |
| 58 | |
| 59 | switch (uType) { |
| 60 | case XTYP_CONNECT: { |
| 61 | if (DdeCmpStringHandles(hsz2, pdfBridgeSumatra.hszServerService)) { |
| 62 | SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "PDFBridgeSumatra DdeCallback Client request connection to unhandled service '%s'", pdfBridgeSumatra.GetDDEString(hsz2).c_str()); |
| 63 | return FALSE; |
| 64 | } else if (DdeCmpStringHandles(hsz1, pdfBridgeSumatra.hszServerTopic)) { |
| 65 | SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "PDFBridgeSumatra DdeCallback Client request connection to unhandled topic '%s'", pdfBridgeSumatra.GetDDEString(hsz1).c_str()); |
| 66 | return FALSE; |
| 67 | } else { |
| 68 | SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "PDFBridgeSumatra DdeCallback Client request connection to service '%s', topic '%s'", pdfBridgeSumatra.GetDDEString(hsz2).c_str(), pdfBridgeSumatra.GetDDEString(hsz1).c_str()); |
| 69 | return reinterpret_cast<HDDEDATA>(TRUE); |
| 70 | } |
| 71 | |
| 72 | break; |
| 73 | } |
| 74 | |
| 75 | case XTYP_CONNECT_CONFIRM: { |
| 76 | SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%s", "PDFBridgeSumatra DdeCallback Client connected"); |
| 77 | break; |
| 78 | } |
| 79 | |
| 80 | case XTYP_EXECUTE: { |
| 81 | size_t len = DdeGetData(hdata, nullptr, 0, 0); // Length of data in bytes (trailing NULL char included) |
| 82 | std::vector<unsigned char> buf(len); |
| 83 | DdeGetData(hdata, buf.data(), buf.size(), 0); // Populate buffer of bytes first |
| 84 | std::vector<wchar_t> wbuf(len / 2); |
| 85 | std::memcpy(wbuf.data(), buf.data(), buf.size()); // Then transfer to buffer of wchar_t |
| 86 | std::wstring wstr(wbuf.data()); // To create a wstring from it |
| 87 | std::string str = utf16_to_utf8(wstr); |
| 88 | |
| 89 | SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "PDFBridgeSumatra DdeCallback Client execute: %s", str.c_str()); |
| 90 | |
| 91 | if (!str.compare(0, 9, "[Search(\"") && !str.compare(str.size() - 3, 3, "\")]")) { |
| 92 | auto searchStr = str.substr(9, str.size() - 9 - 3); // Split parameters between "[Search(" and ")]" |
| 93 | |
| 94 | SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "PDFBridgeSumatra DdeCallback Client Search '%s'", searchStr.c_str()); |
| 95 | pdfBridgeSumatra.reverseSearchStr = searchStr; |
| 96 | pdfBridgeSumatra.reverseSearchStrChanged = true; |
| 97 | |
| 98 | // Push event to SDL queue in order to refresh GUI |
| 99 | SDL_Event sdlEvent; |
| 100 | sdlEvent.type = SDL_USEREVENT; |
| 101 | SDL_PushEvent(&sdlEvent); |
nothing calls this directly
no test coverage detected