⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sumatrapdf.cpp.svn-base

📁 SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多KB)
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
/* Reverse of FileTimeToStr: convert string <s> to <ft>. */void StrToFileTime(char *s, FILETIME* ft){    hexstr_to_mem(s, (unsigned char*)ft, sizeof(*ft));}/* Get current UTS cystem time as string.   Caller needs to free() the result. */char *GetSystemTimeAsStr(){    FILETIME ft;    GetSystemTimeAsFileTime(&ft);    return FileTimeToStr(&ft);}static void FileTimeToLargeInteger(FILETIME *ft, LARGE_INTEGER *lt){    lt->LowPart = ft->dwLowDateTime;    lt->HighPart = ft->dwHighDateTime;}/* Return <ft1> - <ft2> in seconds */DWORD FileTimeDiffInSecs(FILETIME *ft1, FILETIME *ft2){    LARGE_INTEGER t1;    LARGE_INTEGER t2;    FileTimeToLargeInteger(ft1, &t1);    FileTimeToLargeInteger(ft2, &t2);    // diff is in 100 nanoseconds    LONGLONG diff = t1.QuadPart - t2.QuadPart;    diff = diff / (LONGLONG)10000000L;    return (DWORD)diff;}class MemSegment {private:    class MemSegment *next;public:    MemSegment(const void *buf, DWORD size) {        next = NULL;        data = NULL;        add(buf, size);    };    MemSegment() {        next = NULL;        data = NULL;    }    bool add(const void *buf, DWORD size) {        assert(size > 0);        if (!data) {            dataSize = size;            data = malloc(size);            if (!data)                return false;            memcpy(data, buf, size);        } else {            MemSegment *ms = new MemSegment(buf, size);            if (!ms)                return false;            if (!ms->data) {                delete ms;                return false;            }            ms->next = next;            next = ms;        }        return true;    }    void freeAll() {        free(data);        data = NULL;        // clever trick: each segment will delete the next segment        if (next) {            delete next;            next = NULL;        }    }    ~MemSegment() {        freeAll();    }    void *getData(DWORD *sizeOut);    void *data;    DWORD dataSize;};void *MemSegment::getData(DWORD *sizeOut){    DWORD totalSize = dataSize;    MemSegment *curr = next;    while (curr) {        totalSize += curr->dataSize;        curr = curr->next;    }    if (0 == dataSize)        return NULL;    char *buf = (char*)malloc(totalSize + 1); // +1 for 0 termination    if (!buf)        return NULL;    buf[totalSize] = 0;    // the chunks are linked in reverse order, so we must reassemble them properly    char *end = buf + totalSize;    curr = next;    while (curr) {        end -= curr->dataSize;        memcpy(end, curr->data, curr->dataSize);        curr = curr->next;    }    end -= dataSize;    memcpy(end, data, dataSize);    assert(end == buf);    *sizeOut = totalSize;    return (void*)buf;}#ifdef DEBUGvoid u_hexstr(){    unsigned char buf[6] = {1, 2, 33, 255, 0, 18};    unsigned char buf2[6] = {0};    char *s = mem_to_hexstr(buf, sizeof(buf));    BOOL ok = hexstr_to_mem(s, buf2, sizeof(buf2));    assert(ok);    for (int i=0; i<sizeof(buf); i++) {        assert(buf[i] == buf2[i]);    }    free(s);    FILETIME ft1, ft2;    GetSystemTimeAsFileTime(&ft1);    s = FileTimeToStr(&ft1);    StrToFileTime(s, &ft2);    DWORD diff = FileTimeDiffInSecs(&ft1, &ft2);    assert(0 == diff);    assert(ft1.dwLowDateTime == ft2.dwLowDateTime);    assert(ft1.dwHighDateTime == ft2.dwHighDateTime);    free(s);}void u_testMemSegment(){    MemSegment *ms;    DWORD size;    char *data;    char buf[2] = {'a', '\0'};    ms = new MemSegment();    for (int i=0; i<7; i++) {        ms->add(buf, 1);        buf[0] = buf[0] + 1;    }    data = (char*)ms->getData(&size);    delete ms;    assert(str_eq("abcdefg", data));    assert(7 == size);    free(data);    ms = new MemSegment("a", 1);    data = (char*)ms->getData(&size);    ms->freeAll();    delete ms;    assert(str_eq("a", data));    assert(1 == size);    free(data);}#endif// based on information in http://www.codeproject.com/KB/IP/asyncwininet.aspxclass HttpReqCtx {public:    // the window to which we'll send notification about completed download    HWND          hwndToNotify;    // message to send when download is complete    UINT          msg;    // handle for connection during request processing    HINTERNET     httpFile;    char *        url;    MemSegment    data;    /* true for automated check, false for check triggered from menu */    bool          autoCheck;    HttpReqCtx(char *_url, HWND _hwnd, UINT _msg) {        assert(_url);        hwndToNotify = _hwnd;        url = strdup(_url);        msg = _msg;        autoCheck = false;        httpFile = 0;    }    ~HttpReqCtx() {        free(url);        data.freeAll();    }};void __stdcall InternetCallbackProc(HINTERNET hInternet,                        DWORD_PTR dwContext,                        DWORD dwInternetStatus,                        LPVOID statusInfo,                        DWORD statusLen){    char buf[256];    INTERNET_ASYNC_RESULT* res;    HttpReqCtx *ctx = (HttpReqCtx*)dwContext;    switch (dwInternetStatus)    {        case INTERNET_STATUS_HANDLE_CREATED:            res = (INTERNET_ASYNC_RESULT*)statusInfo;            ctx->httpFile = (HINTERNET)(res->dwResult);            _snprintf(buf, 256, "HANDLE_CREATED (%d)", statusLen );            break;        case INTERNET_STATUS_REQUEST_COMPLETE:        {            // Check for errors.            if (LPINTERNET_ASYNC_RESULT(statusInfo)->dwError != 0)            {                _snprintf(buf, 256, "REQUEST_COMPLETE (%d) Error (%d) encountered", statusLen, GetLastError());                break;            }            // Set the resource handle to the HINTERNET handle returned in the callback.            HINTERNET hInt = HINTERNET(LPINTERNET_ASYNC_RESULT(statusInfo)->dwResult);            assert(hInt == ctx->httpFile);            _snprintf(buf, 256, "REQUEST_COMPLETE (%d)", statusLen);            INTERNET_BUFFERSA ib = {0};            ib.dwStructSize = sizeof(ib);            ib.lpvBuffer = malloc(1024);            // This is not exactly async, but we're assuming it'll complete quickly            // because the update file is small and we now that connection is working            // since we already got headers back            BOOL ok;            while (TRUE) {                ib.dwBufferLength = 1024;                ok = InternetReadFileExA(ctx->httpFile, &ib, IRF_ASYNC, (LPARAM)ctx);                if (ok || (!ok && GetLastError()==ERROR_IO_PENDING)) {                    DWORD readSize = ib.dwBufferLength;                    if (readSize > 0) {                        ctx->data.add(ib.lpvBuffer, readSize);                    }                }                if (ok || GetLastError()!=ERROR_IO_PENDING)                    break; // read the whole file or error            }            free(ib.lpvBuffer);            InternetCloseHandle(ctx->httpFile);            ctx->httpFile = 0;            if (ok) {                // read the whole file                PostMessage(ctx->hwndToNotify, ctx->msg, (WPARAM) ctx, 0);            } else {                delete ctx;            }        }        break;#ifdef DEBUG        case INTERNET_STATUS_CLOSING_CONNECTION:            _snprintf(buf, 256, "CLOSING_CONNECTION (%d)", statusLen);            break;        case INTERNET_STATUS_CONNECTED_TO_SERVER:            _snprintf(buf, 256, "CONNECTED_TO_SERVER (%d)", statusLen);            break;        case INTERNET_STATUS_CONNECTING_TO_SERVER:            _snprintf(buf, 256, "CONNECTING_TO_SERVER (%d)", statusLen);            break;        case INTERNET_STATUS_CONNECTION_CLOSED:            _snprintf(buf, 256, "CONNECTION_CLOSED (%d)", statusLen);            break;        case INTERNET_STATUS_HANDLE_CLOSING:            _snprintf(buf, 256, "HANDLE_CLOSING (%d)", statusLen);            break;        case INTERNET_STATUS_INTERMEDIATE_RESPONSE:            _snprintf(buf, 256, "INTERMEDIATE_RESPONSE (%d)", statusLen );            break;        case INTERNET_STATUS_NAME_RESOLVED:            _snprintf(buf, 256, "NAME_RESOLVED (%d)", statusLen);            break;        case INTERNET_STATUS_RECEIVING_RESPONSE:            _snprintf(buf, 256, "RECEIVING_RESPONSE (%d)",statusLen);            break;        case INTERNET_STATUS_RESPONSE_RECEIVED:            _snprintf(buf, 256, "RESPONSE_RECEIVED (%d)", statusLen);            break;        case INTERNET_STATUS_REDIRECT:            _snprintf(buf, 256, "REDIRECT (%d)", statusLen);            break;        case INTERNET_STATUS_REQUEST_SENT:            _snprintf(buf, 256, "REQUEST_SENT (%d)", statusLen);            break;        case INTERNET_STATUS_RESOLVING_NAME:            _snprintf(buf, 256, "RESOLVING_NAME (%d)", statusLen);            break;        case INTERNET_STATUS_SENDING_REQUEST:            _snprintf(buf, 256, "SENDING_REQUEST (%d)", statusLen);            break;        case INTERNET_STATUS_STATE_CHANGE:            _snprintf(buf, 256, "STATE_CHANGE (%d)", statusLen);            break;        default:            _snprintf(buf, 256, "Unknown: Status %d Given", dwInternetStatus);            break;#endif    }    DBG_OUT(buf);    DBG_OUT("\n");}static HINTERNET g_hOpen = NULL;#ifndef SUMATRA_UPDATE_INFO_URL#ifdef SVN_PRE_RELEASE_VER#define SUMATRA_UPDATE_INFO_URL "http://kjkpub.s3.amazonaws.com/sumatrapdf/sumpdf-prerelease-latest.txt"#else#define SUMATRA_UPDATE_INFO_URL "http://blog.kowalczyk.info/software/sumatrapdf/sumpdf-latest.txt"#endif#endif#ifndef SVN_UPDATE_LINK#ifdef SVN_PRE_RELEASE_VERi#define SVN_UPDATE_LINK             "http://blog.kowalczyk.info/software/sumatrapdf/prerelase.html"#else#define SVN_UPDATE_LINK             "http://blog.kowalczyk.info/software/sumatrapdf"#endif#endifbool WininetInit(){    if (!g_hOpen)        g_hOpen = InternetOpenA("SumatraPDF", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);    if (NULL == g_hOpen) {        DBG_OUT("InternetOpenA() failed\n");        return false;    }    return true;}void WininetDeinit(){    if (g_hOpen)        InternetCloseHandle(g_hOpen);}#define SECS_IN_DAY 60*60*24void DownloadSumatraUpdateInfo(WindowInfo *win, bool autoCheck){    if (!WininetInit())        return;    assert(win);    HWND hwndToNotify = win->hwndFrame;    /* For auto-check, only check if at least a day passed since last check */    if (autoCheck && gGlobalPrefs.m_lastUpdateTime) {        FILETIME lastUpdateTimeFt;        StrToFileTime(gGlobalPrefs.m_lastUpdateTime, &lastUpdateTimeFt);        FILETIME currentTimeFt;        GetSystemTimeAsFileTime(&currentTimeFt);        int secs = FileTimeDiffInSecs(&currentTimeFt, &lastUpdateTimeFt);        assert(secs >= 0);        // if secs < 0 => somethings wrong, so ignore that case        if ((secs > 0) && (secs < SECS_IN_DAY))            return;    }    char *url = SUMATRA_UPDATE_INFO_URL "?v=" UPDATE_CHECK_VER;    HttpReqCtx *ctx = new HttpReqCtx(url, hwndToNotify, WM_APP_URL_DOWNLOADED);    ctx->autoCheck = autoCheck;    InternetSetStatusCallback(g_hOpen, (INTERNET_STATUS_CALLBACK)InternetCallbackProc);    HINTERNET urlHandle;    urlHandle = InternetOpenUrlA(g_hOpen, url, NULL, 0,       INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE |       INTERNET_FLAG_NO_CACHE_WRITE, (LPARAM)ctx);    /* MSDN says NULL result from InternetOpenUrlA() means an error, but in my testing       in async mode InternetOpenUrl() returns NULL and error is ERROR_IO_PENDING */    if (!urlHandle && (GetLastError() != ERROR_IO_PENDING)) {        DBG_OUT("InternetOpenUrlA() failed\n");        delete ctx;    }    free(gGlobalPrefs.m_lastUpdateTime);    gGlobalPrefs.m_lastUpdateTime = GetSystemTimeAsStr();}static void SerializableGlobalPrefs_Init() {    gGlobalPrefs.m_inverseSearchCmdLine = strdup(DEFAULT_INVERSE_SEARCH_COMMANDLINE);}static void SerializableGlobalPrefs_Deinit(){    free(gGlobalPrefs.m_versionToSkip);    free(gGlobalPrefs.m_inverseSearchCmdLine);    free(gGlobalPrefs.m_lastUpdateTime);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -