Пример #1
0
static LRESULT CALLBACK
html_proc(HWND win, UINT msg, WPARAM wp, LPARAM lp)
{
    html_t* html = (html_t*) GetWindowLongPtr(win, 0);

    if(html != NULL  &&  html->ie_win == NULL) {
        /* Let's try to subclass IE window. This is very dirty hack,
         * which allows us to forward keyboard messages properly to
         * IOleInPlaceActiveObject::TranslateAccelerator().
         *
         * Normally this should be done from main app. loop but we do not
         * have it under control in the DLL. */
        html->ie_win = html_find_ie_window(win);
        if(html->ie_win != NULL) {
            HTML_TRACE("html_proc: Subclassing MSIE.");
            html->ie_proc = (WNDPROC) SetWindowLongPtr(html->ie_win,
                            GWLP_WNDPROC, (LONG_PTR) html_ie_subclass_proc);
            SetProp(html->ie_win, ie_prop, (HANDLE) html);

            if(GetFocus() == win) {
                SetFocus(html->ie_win);
                MC_SEND(html->ie_win, WM_LBUTTONDOWN, 0, 0);
                MC_SEND(html->ie_win, WM_LBUTTONUP, 0, 0);
            }
        }
    }

    switch(msg) {
        case MC_HM_GOTOURLW:
        case MC_HM_GOTOURLA:
        {
            int res = html_goto_url(html, (const void*)lp, (msg == MC_HM_GOTOURLW));
            return (res == 0 ? TRUE : FALSE);
        }

        case MC_HM_SETTAGCONTENTSW:
        case MC_HM_SETTAGCONTENTSA:
        {
            int res = html_set_element_contents(html, (void*)wp, (void*)lp,
                                                (msg == MC_HM_SETTAGCONTENTSW));
            return (res == 0 ? TRUE : FALSE);
        }

        case MC_HM_GOBACK:
        {
            int res = html_goto_back(html, wp);
            return (res == 0 ? TRUE : FALSE);
        }

        case MC_HM_CANBACK:
            return ((wp ? html->can_back : html->can_forward) ? TRUE : FALSE);

        case WM_SIZE:
        {
            IWebBrowser2* browser_iface;
            HRESULT hr;

            hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj,
                        &IID_IWebBrowser2, (void**)&browser_iface);
            if(hr == S_OK  &&  browser_iface != NULL) {
                browser_iface->lpVtbl->put_Width(browser_iface, LOWORD(lp));
                browser_iface->lpVtbl->put_Height(browser_iface, HIWORD(lp));
                browser_iface->lpVtbl->Release(browser_iface);
            }
            return 0;
        }

        case WM_STYLECHANGED:
            if(wp == GWL_STYLE) {
                STYLESTRUCT* ss = (STYLESTRUCT*) lp;
                html->style = ss->styleNew;
                RedrawWindow(win, NULL, NULL,
                             RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN);
            }
            break;

        case WM_NOTIFYFORMAT:
            switch(lp) {
                case NF_REQUERY:
                    html_notify_format(html);
                    return (html->unicode_notifications ? NFR_UNICODE : NFR_ANSI);
                case NF_QUERY:
                    return (MC_IS_UNICODE ? NFR_UNICODE : NFR_ANSI);
            }
            break;

        case CCM_SETUNICODEFORMAT:
        {
            BOOL tmp = html->unicode_notifications;
            html->unicode_notifications = (wp != 0);
            return tmp;
        }

        case CCM_GETUNICODEFORMAT:
            return html->unicode_notifications;

        case CCM_SETNOTIFYWINDOW:
        {
            HWND old = html->notify_win;
            html->notify_win = (wp ? (HWND) wp : GetAncestor(win, GA_PARENT));
            return (LPARAM) old;
        }

        case WM_SETFOCUS:
            if(html->ie_win) {
                SetFocus(html->ie_win);
                MC_SEND(html->ie_win, WM_LBUTTONDOWN, 0, 0);
                MC_SEND(html->ie_win, WM_LBUTTONUP, 0, 0);
            }
            return 0;

        case WM_GETDLGCODE:
            return DLGC_WANTALLKEYS;

        case WM_SETTEXT:
            return FALSE;

        case WM_GETTEXT:
            if(wp > 0)
                ((TCHAR*)lp)[0] = _T('\0');
            return 0;

        case WM_GETTEXTLENGTH:
            return 0;

        case WM_NCCREATE:
            html = html_nccreate(win, (CREATESTRUCT*)lp);
            if(MC_ERR(html == NULL))
                return FALSE;
            SetWindowLongPtr(win, 0, (LONG_PTR)html);
            return TRUE;

        case WM_CREATE:
            return (html_create(html, (CREATESTRUCT*)lp) == 0 ? 0 : -1);

        case WM_DESTROY:
            html_destroy(html);
            return 0;

        case WM_NCDESTROY:
            if(html)
                html_ncdestroy(html);
            return 0;
    }

    /* Forward keystrokes to the IE */
    if(WM_KEYFIRST <= msg  &&  msg <= WM_KEYLAST) {
        if(html->ie_win)
            MC_SEND(html->ie_win, msg, wp, lp);
        return 0;
    }

    return DefWindowProc(win, msg, wp, lp);
}
Пример #2
0
static HRESULT STDMETHODCALLTYPE
dispatch_Invoke(IDispatch* self, DISPID disp_id, REFIID riid, LCID lcid,
                WORD flags, DISPPARAMS* params, VARIANT* var_res,
                EXCEPINFO* except, UINT* arg_err)
{
    html_t* html = MC_HTML_FROM_DISPTACH(self);

    switch(disp_id) {
        case DISPID_BEFORENAVIGATE2:
        {
            BSTR url = V_BSTR(V_VARIANTREF(&params->rgvarg[5]));
            VARIANT_BOOL* cancel = V_BOOLREF(&params->rgvarg[0]);

            HTML_TRACE("dispatch_Invoke: DISPID_BEFORENAVIGATE2(%S)", url);

            if(url != NULL  &&  wcsncmp(url, L"app:", 4) == 0) {
                html_notify_text(html, MC_HN_APPLINK, url);
                *cancel = VARIANT_TRUE;
            }
            break;
        }

#if 0
        /* Unfortunately, IE does not send DISPID_DOCUMENTCOMPLETE
         * when refreshing the page (e.g. from context menu). So we workaround
         * via DISPID_PROGRESSCHANGE below. */
        case DISPID_DOCUMENTCOMPLETE:
        {
            BSTR url = V_BSTR(V_VARIANTREF(&params->rgvarg[0]));
            html_notify_text(html, MC_HN_DOCUMENTCOMPLETE, url);
            break;
        }
#endif

        case DISPID_PROGRESSCHANGE:
        {
            LONG progress_max = V_I4(&params->rgvarg[0]);
            LONG progress = V_I4(&params->rgvarg[1]);
            MC_NMHTMLPROGRESS notify;
            HTML_TRACE("dispatch_Invoke: DISPID_PROGRESSCHANGE(%ld, %ld)",
                       progress, progress_max);

            /* Send also notification about the progress */
            notify.hdr.hwndFrom = html->win;
            notify.hdr.idFrom = GetDlgCtrlID(html->win);
            notify.hdr.code = MC_HN_PROGRESS;
            notify.lProgress = progress;
            notify.lProgressMax = progress_max;
            MC_SEND(html->notify_win, WM_NOTIFY, notify.hdr.idFrom, &notify);

            /* This replaces DISPID_DOCUMENTCOMPLETE above */
            if(progress < 0  ||  progress_max < 0) {
                IWebBrowser2* browser_iface;
                HRESULT hr;

                hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj,
                        &IID_IWebBrowser2, (void**)&browser_iface);
                if(MC_ERR(hr != S_OK  ||  browser_iface == NULL)) {
                    MC_TRACE("dispatch_Invoke(DISPID_PROGRESSCHANGE): "
                             "QueryInterface(IID_IWebBrowser2) failed [0x%lx]", hr);
                } else {
                    BSTR url = NULL;
                    hr = browser_iface->lpVtbl->get_LocationURL(browser_iface, &url);
                    if(hr == S_OK && url != NULL) {
                        html_notify_text(html, MC_HN_DOCUMENTCOMPLETE, url);
                        html_SysFreeString(url);
                    }
                    browser_iface->lpVtbl->Release(browser_iface);
                }
            }
            break;
        }

        case DISPID_STATUSTEXTCHANGE:
            HTML_TRACE("dispatch_Invoke: DISPID_STATUSTEXTCHANGE");
            html_notify_text(html, MC_HN_STATUSTEXT, V_BSTR(&params->rgvarg[0]));
            break;

        case DISPID_TITLECHANGE:
            HTML_TRACE("dispatch_Invoke: DISPID_TITLECHANGE");
            html_notify_text(html, MC_HN_TITLETEXT, V_BSTR(&params->rgvarg[0]));
            break;

        case DISPID_COMMANDSTATECHANGE:
        {
            LONG cmd = V_I4(&params->rgvarg[1]);
            HTML_TRACE("dispatch_Invoke: DISPID_COMMANDSTATECHANGE");

            if(cmd == CSC_NAVIGATEBACK  ||  cmd == CSC_NAVIGATEFORWARD) {
                MC_NMHTMLHISTORY notify;
                BOOL enabled = (V_BOOL(&params->rgvarg[0]) != VARIANT_FALSE);

                if(cmd == CSC_NAVIGATEBACK)
                    html->can_back = enabled;
                else
                    html->can_forward = enabled;

                notify.hdr.hwndFrom = html->win;
                notify.hdr.idFrom = GetDlgCtrlID(html->win);
                notify.hdr.code = MC_HN_HISTORY;
                notify.bCanBack = html->can_back;
                notify.bCanForward = html->can_forward;
                MC_SEND(html->notify_win, WM_NOTIFY, notify.hdr.idFrom, &notify);
            }
            break;
        }

        case DISPID_NEWWINDOW2:
        /* This is called instead of DISPID_NEWWINDOW3 on Windows XP SP2
         * and older. */
        {
            VARIANT_BOOL* cancel = V_BOOLREF(&params->rgvarg[0]);
            HTML_TRACE("dispatch_Invoke: DISPID_NEWWINDOW2");

            if(html_notify_text(html, MC_HN_NEWWINDOW, L"") == 0) {
                *cancel = VARIANT_TRUE;
                HTML_TRACE("dispatch_Invoke(DISPID_NEWWINDOW2): Canceled.");
            }
            break;
        }

        case DISPID_NEWWINDOW3:
        {
            BSTR url = V_BSTR(&params->rgvarg[0]);
            VARIANT_BOOL* cancel = V_BOOLREF(&params->rgvarg[3]);
            HTML_TRACE("dispatch_Invoke: DISPID_NEWWINDOW3");

            if(html_notify_text(html, MC_HN_NEWWINDOW, url) == 0) {
                *cancel = VARIANT_TRUE;
                HTML_TRACE("dispatch_Invoke(DISPID_NEWWINDOW3, '%S'): Canceled.", url);
            }
            break;
        }

        default:
            HTML_TRACE("dispatch_Invoke: unsupported disp_id %d", disp_id);
            return DISP_E_MEMBERNOTFOUND;
    }

    return S_OK;
}
Пример #3
0
static int
html_create(html_t* html, CREATESTRUCT* cs)
{
    IWebBrowser2* browser_iface = NULL;
    IConnectionPointContainer* conn_point_container;
    IConnectionPoint* conn_point;
    DWORD cookie;
    RECT rect;
    HRESULT hr;

    /* Initialize OLE. It is here and not in html_init() because it has to
     * be performed in the thread where OLE shall be used (i.e. where
     * the message loop controlling the window is running). */
    hr = html_OleInitialize(NULL);
    if(MC_ERR(FAILED(hr))) {
        MC_TRACE("html_create: OleInitialize() failed [0x%lx]", hr);
        return -1;
    }

    html->ole_initialized = 1;

    /* Create browser object */
    hr = html_CoCreateInstance(&CLSID_WebBrowser, NULL, CLSCTX_INPROC,
            &IID_IOleObject, (void**)&html->browser_obj);
    if(MC_ERR(FAILED(hr))) {
        MC_TRACE("html_create: CoCreateInstance(CLSID_WebBrowser) failed "
                 "[0x%lx]", hr);
        return -1;
    }

    /* Embed the browser object into our host window */
    hr = html->browser_obj->lpVtbl->SetClientSite(html->browser_obj,
                &html->client_site);
    if(MC_ERR(FAILED(hr))) {
        MC_TRACE("html_create: IOleObject::SetClientSite() failed [0x%lx]", hr);
        return -1;
    }
    GetClientRect(html->win, &rect);
    hr = html->browser_obj->lpVtbl->DoVerb(html->browser_obj, OLEIVERB_INPLACEACTIVATE,
                            NULL, &html->client_site, 0, html->win, &rect);
    if(MC_ERR(FAILED(hr))) {
        MC_TRACE("html_create: IOleObject::DoVerb(OLEIVERB_INPLACEACTIVATE) "
                 "failed [0x%lx]", hr);
        return -1;
    }

    /* Send events of DIID_DWebBrowserEvents2 to our IDispatch */
    hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj,
                &IID_IConnectionPointContainer, (void**)&conn_point_container);
    if(MC_ERR(hr != S_OK  ||  conn_point_container == NULL)) {
        MC_TRACE("html_create: QueryInterface(IID_IConnectionPointContainer) failed "
                 "[0x%lx]", hr);
        return -1;
    }
    hr = conn_point_container->lpVtbl->FindConnectionPoint(conn_point_container,
                &DIID_DWebBrowserEvents2, &conn_point);
    conn_point_container->lpVtbl->Release(conn_point_container);
    if(MC_ERR(FAILED(hr))) {
        MC_TRACE("html_create: FindConnectionPoint(DIID_DWebBrowserEvents2) failed "
                 "[0x%lx]", hr);
        return -1;
    }
    conn_point->lpVtbl->Advise(conn_point, (IUnknown*)&html->client_site, &cookie);
    conn_point->lpVtbl->Release(conn_point);

    /* Set browser position and size according to the host window */
    hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj,
                &IID_IWebBrowser2, (void**)&browser_iface);
    if(MC_ERR(hr != S_OK  ||  browser_iface == NULL)) {
        MC_TRACE("html_create: QueryInterface(IID_IWebBrowser2) failed "
                 "[0x%lx]", hr);
        return -1;
    }
    browser_iface->lpVtbl->put_Left(browser_iface, 0);
    browser_iface->lpVtbl->put_Top(browser_iface, 0);
#if 0  /* these are set in WM_SIZE handler */
    browser_iface->lpVtbl->put_Width(browser_iface, MC_WIDTH(&rect));
    browser_iface->lpVtbl->put_Height(browser_iface, MC_HEIGHT(&rect));
#endif
    browser_iface->lpVtbl->Release(browser_iface);

    /* Goto specified URL if any */
    if(cs->lpszName != NULL && cs->lpszName[0] != _T('\0'))
        html_goto_url(html, cs->lpszName, MC_IS_UNICODE);

    return 0;
}
Пример #4
0
static int
html_set_element_contents(html_t* html, const void* id, const void* contents,
                          BOOL unicode)
{
    BSTR bstr_id;
    BSTR bstr_contents;
    IWebBrowser2* browser_iface;
    IDispatch* dispatch_iface;
    IHTMLDocument3* doc_iface;
    IHTMLElement* elem_iface;
    HRESULT hr;
    int res = -1;

    if(MC_ERR(id == NULL  ||  (unicode && ((WCHAR*)id)[0] == L'\0')  ||
                              (!unicode && ((char*)id)[0] == '\0'))) {
        MC_TRACE("html_set_element_contents: Empty element ID.");
        SetLastError(ERROR_INVALID_PARAMETER);
        goto err_id;
    }
    bstr_id = html_bstr(id, (unicode ? MC_STRW : MC_STRA));
    if(MC_ERR(bstr_id == NULL)) {
        MC_TRACE("html_set_element_contents: html_bstr(id) failed.");
        mc_send_notify(html->notify_win, html->win, NM_OUTOFMEMORY);
        goto err_id;
    }

    bstr_contents = html_bstr(contents, (unicode ? MC_STRW : MC_STRA));
    if(MC_ERR(bstr_contents == NULL)) {
        MC_TRACE("html_set_element_contents: html_bstr(contents) failed");
        mc_send_notify(html->notify_win, html->win, NM_OUTOFMEMORY);
        goto err_contents;
    }

    hr = html->browser_obj->lpVtbl->QueryInterface(html->browser_obj,
                    &IID_IWebBrowser2, (void**)&browser_iface);
    if(MC_ERR(hr != S_OK  ||  browser_iface == NULL)) {
        MC_TRACE("html_set_element_contents: "
                 "QueryInterface(IID_IWebBrowser2) failed [0x%lx]", hr);
        goto err_browser;
    }

    hr = browser_iface->lpVtbl->get_Document(browser_iface, &dispatch_iface);
    if(MC_ERR(FAILED(hr)  ||  dispatch_iface == NULL)) {
        MC_TRACE("html_set_element_contents: get_Document() failed [0x%lx]", hr);
        goto err_dispatch;
    }

    hr = dispatch_iface->lpVtbl->QueryInterface(dispatch_iface,
                                    &IID_IHTMLDocument3, (void**)&doc_iface);
    if(MC_ERR(hr != S_OK  ||  doc_iface == NULL)) {
        MC_TRACE("html_set_element_contents: "
                 "QueryInterface(IID_IHTMLDocument3) failed [0x%lx]", hr);
        goto err_doc;
    }

    hr = doc_iface->lpVtbl->getElementById(doc_iface, bstr_id, &elem_iface);
    if(MC_ERR(FAILED(hr)  ||  elem_iface == NULL)) {
        MC_TRACE("html_set_element_contents: getElementById() failed [0x%lx]", hr);
        goto err_elem;
    }

    hr = elem_iface->lpVtbl->put_innerHTML(elem_iface, bstr_contents);
    if(MC_ERR(hr != S_OK)) {
        MC_TRACE("html_set_element_contents: put_innerHTML() failed [0x%lx]", hr);
        goto err_inner_html;
    }

    res = 0;

err_inner_html:
    elem_iface->lpVtbl->Release(elem_iface);
err_elem:
    doc_iface->lpVtbl->Release(doc_iface);
err_doc:
    dispatch_iface->lpVtbl->Release(dispatch_iface);
err_dispatch:
    browser_iface->lpVtbl->Release(browser_iface);
err_browser:
    html_SysFreeString(bstr_contents);
err_contents:
    html_SysFreeString(bstr_id);
err_id:
    return res;
}
Пример #5
0
static LRESULT CALLBACK
grid_proc(HWND win, UINT msg, WPARAM wp, LPARAM lp)
{
    grid_t* grid = (grid_t*) GetWindowLongPtr(win, 0);

    switch(msg) {
        case WM_PAINT:
            return generic_paint(win, grid->no_redraw,
                                 (grid->style & MC_GS_DOUBLEBUFFER),
                                 grid_paint, grid);

        case WM_PRINTCLIENT:
            return generic_printclient(win, (HDC) wp, grid_paint, grid);

        case WM_NCPAINT:
            return generic_ncpaint(win, grid->theme_listview, (HRGN) wp);

        case WM_ERASEBKGND:
            return generic_erasebkgnd(win, grid->theme_listview, (HDC) wp);

        case MC_GM_GETTABLE:
            return (LRESULT) grid->table;

        case MC_GM_SETTABLE:
            return (grid_set_table(grid, (table_t*) lp) == 0 ? TRUE : FALSE);

        case MC_GM_GETCOLUMNCOUNT:
            return grid->col_count;

        case MC_GM_GETROWCOUNT:
            return grid->row_count;

        case MC_GM_RESIZE:
            return (grid_resize_table(grid, LOWORD(wp), HIWORD(wp)) == 0 ? TRUE : FALSE);

        case MC_GM_CLEAR:
            return (grid_clear(grid, wp) == 0 ? TRUE : FALSE);

        case MC_GM_SETCELLW:
        case MC_GM_SETCELLA:
            return (grid_set_cell(grid, LOWORD(wp), HIWORD(wp), (MC_TABLECELL*)lp,
                                  (msg == MC_GM_SETCELLW)) == 0 ? TRUE : FALSE);

        case MC_GM_GETCELLW:
        case MC_GM_GETCELLA:
            return (grid_get_cell(grid, LOWORD(wp), HIWORD(wp), (MC_TABLECELL*)lp,
                                  (msg == MC_GM_GETCELLW)) == 0 ? TRUE : FALSE);

        case MC_GM_SETGEOMETRY:
            return (grid_set_geometry(grid, (MC_GGEOMETRY*)lp, TRUE) == 0 ? TRUE : FALSE);

        case MC_GM_GETGEOMETRY:
            return (grid_get_geometry(grid, (MC_GGEOMETRY*)lp) == 0 ? TRUE : FALSE);

        case MC_GM_REDRAWCELLS:
            return (grid_redraw_cells(grid, LOWORD(wp), HIWORD(wp),
                                      LOWORD(lp), LOWORD(lp)) == 0 ? TRUE : FALSE);

        case MC_GM_SETCOLUMNWIDTH:
            return (grid_set_col_width(grid, wp, LOWORD(lp)) == 0 ? TRUE : FALSE);

        case MC_GM_GETCOLUMNWIDTH:
            return grid_get_col_width(grid, wp);

        case MC_GM_SETROWHEIGHT:
            return (grid_set_row_height(grid, wp, LOWORD(lp)) == 0 ? TRUE : FALSE);

        case MC_GM_GETROWHEIGHT:
            return grid_get_row_height(grid, wp);

        case WM_SETREDRAW:
            grid->no_redraw = !wp;
            return 0;

        case WM_VSCROLL:
        case WM_HSCROLL:
            grid_scroll(grid, (msg == WM_VSCROLL), LOWORD(wp), 1);
            return 0;

        case WM_MOUSEWHEEL:
        case WM_MOUSEHWHEEL:
            grid_mouse_wheel(grid, (msg == WM_MOUSEWHEEL), (int)(SHORT)HIWORD(wp));
            return 0;

        case WM_SIZE:
            if(!grid->no_redraw) {
                int old_scroll_x = grid->scroll_x;
                int old_scroll_y = grid->scroll_y;

                grid_setup_scrollbars(grid, FALSE);

                if(grid->scroll_x != old_scroll_x || grid->scroll_y != old_scroll_y)
                    InvalidateRect(win, NULL, TRUE);
            }
            return 0;

        case WM_GETFONT:
            return (LRESULT) grid->font;

        case WM_SETFONT:
            grid->font = (HFONT) wp;
            if((BOOL) lp  &&  !grid->no_redraw)
                InvalidateRect(win, NULL, TRUE);
            return 0;

        case WM_STYLECHANGED:
            if(wp == GWL_STYLE)
                grid_style_changed(grid, (STYLESTRUCT*) lp);
            break;

        case WM_THEMECHANGED:
            grid_close_theme(grid);
            grid_open_theme(grid);
            if(!grid->no_redraw)
                RedrawWindow(win, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE);
            return 0;

        case WM_SYSCOLORCHANGE:
            if(!grid->no_redraw)
                RedrawWindow(win, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE);
            return 0;

        case WM_NOTIFYFORMAT:
            if(lp == NF_REQUERY)
                grid_notify_format(grid);
            return (grid->unicode_notifications ? NFR_UNICODE : NFR_ANSI);

        case CCM_SETUNICODEFORMAT:
        {
            BOOL old = grid->unicode_notifications;
            grid->unicode_notifications = (wp != 0);
            return old;
        }

        case CCM_GETUNICODEFORMAT:
            return grid->unicode_notifications;

        case CCM_SETNOTIFYWINDOW:
        {
            HWND old = grid->notify_win;
            grid->notify_win = (wp ? (HWND) wp : GetAncestor(win, GA_PARENT));
            return (LRESULT) old;
        }

        case CCM_SETWINDOWTHEME:
            mcSetWindowTheme(win, (const WCHAR*) lp, NULL);
            return 0;

        case WM_NCCREATE:
            grid = grid_nccreate(win, (CREATESTRUCT*)lp);
            if(MC_ERR(grid == NULL))
                return FALSE;
            SetWindowLongPtr(win, 0, (LONG_PTR)grid);
            return TRUE;

        case WM_CREATE:
            return (grid_create(grid) == 0 ? 0 : -1);

        case WM_DESTROY:
            grid_destroy(grid);
            return 0;

        case WM_NCDESTROY:
            if(grid)
                grid_ncdestroy(grid);
            return 0;
    }

    return DefWindowProc(win, msg, wp, lp);
}
Пример #6
0
static int
grid_set_table(grid_t* grid, table_t* table)
{
    if(table != NULL && table == grid->table)
        return 0;

    if(MC_ERR(table != NULL  &&  (grid->style & MC_GS_OWNERDATA))) {
        MC_TRACE("grid_set_table: Cannot install table while having style "
                 "MC_GS_OWNERDATA");
        SetLastError(ERROR_INVALID_STATE);
        return -1;
    }

    if(table != NULL) {
        table_ref(table);
    } else if(!(grid->style & (MC_GS_NOTABLECREATE | MC_GS_OWNERDATA))) {
        table = table_create(0, 0);
        if(MC_ERR(table == NULL)) {
            MC_TRACE("grid_set_table: table_create() failed.");
            return -1;
        }
    }

    if(table != NULL) {
        if(MC_ERR(table_install_view(table, grid, grid_refresh)) != 0) {
            MC_TRACE("grid_set_table: table_install_view() failed.");
            table_unref(table);
            return -1;
        }
    }

    if(grid->table != NULL) {
        table_uninstall_view(grid->table, grid);
        table_unref(grid->table);
    }

    grid->table = table;

    if(table != NULL) {
        grid->col_count = table->col_count;
        grid->row_count = table->row_count;
    } else {
        grid->col_count = 0;
        grid->row_count = 0;
    }

    grid->cache_hint[0] = 0;
    grid->cache_hint[1] = 0;
    grid->cache_hint[2] = 0;
    grid->cache_hint[3] = 0;

    if(grid->col_widths != NULL) {
        free(grid->col_widths);
        grid->col_widths = NULL;
    }

    if(grid->row_heights != NULL) {
        free(grid->row_heights);
        grid->row_heights = NULL;
    }

    if(!grid->no_redraw) {
        InvalidateRect(grid->win, NULL, TRUE);
        grid_setup_scrollbars(grid, TRUE);
    }
    return 0;
}
Пример #7
0
void*
xcom_init_create(const CLSID* clsid, DWORD context, const IID* iid)
{
    void* obj;
    HRESULT hr;

redo:
    switch(xcom_mode) {
        case XCOM_MODE_APP:
            /* The application already initialized COM so we do not manage it
             * at all and just reuse app's apartment. */
            hr = CoCreateInstance(clsid, NULL, context, iid, &obj);
            if(MC_ERR(FAILED(hr))) {
                MC_TRACE_HR("xcom_create_init: CoCreateInstance(1) failed.");
                return NULL;
            }
            return obj;

        case XCOM_MODE_MCTRL:
            /* We are responsible to initialize COM whenever we want to use
             * it. According to Raymond Chen, we should use single-threaded
             * apartment (COINIT_APARTMENTTHREADED):
             * http://blogs.msdn.com/b/oldnewthing/archive/2008/04/24/8420242.aspx
             */
            hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
            if(MC_ERR(FAILED(hr))) {
                MC_TRACE_HR("xcom_create_init: CoInitializeEx() failed.");
                return NULL;
            }
            hr = CoCreateInstance(clsid, NULL, context, iid, &obj);
            if(MC_ERR(FAILED(hr))) {
                MC_TRACE_HR("xcom_create_init: CoCreateInstance(2) failed.");
                CoUninitialize();
                return NULL;
            }
            return obj;

        case XCOM_MODE_UNKNOWN:
            EnterCriticalSection(&xcom_lock);
            if(xcom_mode != XCOM_MODE_UNKNOWN) {   /* Resolve a race. */
                LeaveCriticalSection(&xcom_lock);
                goto redo;
            }
            hr = CoCreateInstance(clsid, NULL, context, iid, &obj);
            if(SUCCEEDED(hr)) {
                xcom_mode = XCOM_MODE_APP;
            } else if(hr == CO_E_NOTINITIALIZED) {
                xcom_mode = XCOM_MODE_MCTRL;
            } else {
                MC_TRACE_HR("xcom_create_init: CoCreateInstance(3) failed.");
                obj = NULL;
            }
            LeaveCriticalSection(&xcom_lock);
            if(hr == CO_E_NOTINITIALIZED)
                goto redo;
            return obj;

        default:
            MC_UNREACHABLE;
            return NULL;
    }
}