コード例 #1
0
ファイル: grid.c プロジェクト: UIKit0/mctrl
static void
grid_region_rect(grid_t* grid, WORD col0, WORD row0,
                 WORD col1, WORD row1, RECT* rect)
{
    int header_w, header_h;

    /* Note: Caller may never mix header and ordinary cells in one call,
     * because the latter is scrolled area, while the headers are not. Hence
     * it does not make any sense to mix theme together. */
    MC_ASSERT(col1 > col0  ||  col0 == MC_TABLE_HEADER);
    MC_ASSERT(row1 > row0  ||  row0 == MC_TABLE_HEADER);

    header_w = grid_header_width(grid);
    header_h = grid_header_height(grid);

    if(col0 == MC_TABLE_HEADER) {
        rect->left = 0;
        rect->right = header_w;
    } else {
        rect->left = grid_col_x(grid, col0);
        rect->right = grid_col_x2(grid, col0, rect->left, col1);
    }

    if(row0 == MC_TABLE_HEADER) {
        rect->top = 0;
        rect->bottom = header_h;
    } else {
        rect->top = grid_row_y(grid, row0);
        rect->bottom = grid_row_y2(grid, row0, rect->top, row1);
    }
}
コード例 #2
0
ファイル: debug.c プロジェクト: UIKit0/mctrl
void*
debug_realloc(const char* fname, int line, void* mem, size_t size)
{
    void* new_mem;

    new_mem = debug_malloc(fname, line, size);
    if(MC_ERR(new_mem == NULL))
        return NULL;

    /* Copy contents from the old memory chunk */
    if(mem != NULL) {
        mem_info_t* mi;
        mi = mem_hashtable[MEM_HASHTABLE_INDEX(mem)];
        while(mi->mem != mem) {
            if(MC_ERR(mi == NULL)) {
                /* Not registered? */
                MC_TRACE("%s:%d: \tdebug_realloc(%p): Attempting to realloc "
                         "non-allocated memory.", fname, line, mem);
                MC_ASSERT(1 == 0);
            }
            mi = mi->next;
        }
        memcpy(new_mem, mem, MC_MIN(size, mi->size));
        debug_free(fname, line, mem);
    }

    return new_mem;
}
コード例 #3
0
ファイル: html.c プロジェクト: ArmstrongJ/mctrl
static BSTR
html_bstr(const void* from_str, int from_type)
{
    WCHAR* str_w;
    BSTR str_b;

    if(from_str == NULL) {
        /* According to MSDN, BSTR should never be NULL. */
        from_str = L"";
        from_type = MC_STRW;
    }

    if(from_type == MC_STRW) {
        str_w = (WCHAR*) from_str;
    } else {
        char* str_a;
        MC_ASSERT(from_type == MC_STRA);
        str_a = (char*) from_str;
        str_w = (WCHAR*) mc_str(str_a, from_type, MC_STRW);
        if(MC_ERR(str_w == NULL)) {
            MC_TRACE("html_bstr: mc_str() failed.");
            return NULL;
        }
    }

    str_b = html_SysAllocString(str_w);
    if(MC_ERR(str_b == NULL))
        MC_TRACE("html_bstr: SysAllocString() failed.");

    if(str_w != from_str)
        free(str_w);

    return str_b;
}
コード例 #4
0
ファイル: html.c プロジェクト: GeonHun/mctrl
static BSTR
html_bstr(const void* from_str, int from_type)
{
    WCHAR* str_w;
    BSTR str_b;

    if(from_str == NULL)
        return NULL;

    if(from_type == MC_STRW) {
        str_w = (WCHAR*) from_str;
        if(str_w[0] == L'\0')
            return NULL;
    } else {
        char* str_a;
        MC_ASSERT(from_type == MC_STRA);
        str_a = (char*) from_str;
        if(str_a[0] == '\0')
            return NULL;
        str_w = (WCHAR*) mc_str(str_a, from_type, MC_STRW);
        if(MC_ERR(str_w == NULL)) {
            MC_TRACE("html_bstr: mc_str() failed.");
            return NULL;
        }
    }

    str_b = html_SysAllocString(str_w);
    if(MC_ERR(str_b == NULL))
        MC_TRACE("html_bstr: SysAllocString() failed.");

    if(from_type == MC_STRA)
        free(str_w);

    return str_b;
}
コード例 #5
0
ファイル: debug.c プロジェクト: UIKit0/mctrl
void
debug_init(void)
{
    InitializeCriticalSection(&mem_lock);

    /* We guard the heap with our own locking as we need the critical section
     * around it anyway. Hence HEAP_NO_SERIALIZE. */
    mem_heap = HeapCreate(HEAP_NO_SERIALIZE, 1024 * 16 * sizeof(mem_info_t), 0);
    MC_ASSERT(mem_heap != NULL);
}
コード例 #6
0
ファイル: grid.c プロジェクト: UIKit0/mctrl
static void
grid_paint_header_cell(grid_t* grid, WORD col, WORD row, table_cell_t* cell,
                       HDC dc, RECT* rect, int index, DWORD style)
{
    table_cell_t tmp;
    table_cell_t* tmp_cell = &tmp;
    TCHAR buffer[16];
    DWORD fabricate;

    /* Paint header background. */
    if(grid->theme_header != NULL) {
        mcDrawThemeBackground(grid->theme_header, dc,
                              HP_HEADERITEM, HIS_NORMAL, rect, NULL);
    } else {
        DrawEdge(dc, rect, BDR_RAISEDINNER, BF_MIDDLE | BF_RECT);
    }

    /* The 'dead' cell cannot have any contents. */
    if(index < 0)
        return;

    /* Retrieve (or fabricate) cell to be painted. */
    fabricate = (style & (MC_GS_COLUMNHEADERMASK | MC_GS_ROWHEADERMASK));
    if(!fabricate) {
        /* Make copy so we can reset alignment flags below w/o side effects. */
        if(cell != NULL)
            memcpy(&tmp, cell, sizeof(table_cell_t));
        else
            tmp_cell = NULL;
    } else {
        if(fabricate == MC_GS_COLUMNHEADERNUMBERED  ||
           fabricate == MC_GS_ROWHEADERNUMBERED)
        {
            _stprintf(buffer, _T("%d"), index + 1);
            tmp.text = buffer;
        } else {
            MC_ASSERT(fabricate == MC_GS_COLUMNHEADERALPHABETIC  ||
                      fabricate == MC_GS_ROWHEADERALPHABETIC);
            tmp.text = grid_alphabetic_number(buffer, index);
        }
        tmp.flags = (cell != NULL ? cell->flags : 0);
        tmp.is_value = FALSE;
    }

    /* If the header does not say explicitly otherwise, force centered
     * alignment for the header cells. */
    if((tmp.flags & VALUE_PF_ALIGNMASKHORZ) == VALUE_PF_ALIGNDEFAULT)
        tmp.flags |= VALUE_PF_ALIGNCENTER;
    if((tmp.flags & VALUE_PF_ALIGNMASKVERT) == VALUE_PF_ALIGNVDEFAULT)
        tmp.flags |= VALUE_PF_ALIGNVCENTER;

    /* Paint header contents. */
    grid_paint_cell(grid, col, row, tmp_cell, dc, rect);
}
コード例 #7
0
ファイル: debug.c プロジェクト: UIKit0/mctrl
void*
debug_malloc(const char* fname, int line, size_t size)
{
    BYTE* buffer;
    void* mem;
    mem_info_t* mi;

    /* We never attempt to allocate zero bytes in mCtrl */
    MC_ASSERT(size > 0);

    /* Allocate */
    buffer = (BYTE*) malloc(size + sizeof(head_guard) + sizeof(tail_guard));
    if(MC_ERR(buffer == NULL)) {
        MC_TRACE("%s:%d: \tdebug_malloc(%lu) failed.", fname, line, (ULONG)size);
        return NULL;
    }

    /* Setup over/underrun guards */
    memcpy(buffer, head_guard, sizeof(head_guard));
    memcpy(buffer + sizeof(head_guard) + size, tail_guard, sizeof(tail_guard));

    /* Fill the memory chunk with some non-zero bytes
     * (this can help to debug (mis)uses of uninitialized memory) */
    mem = (void*)(buffer + sizeof(head_guard));
    memset(mem, 0xff, size);

    /* Register info about the allocated memory */
    EnterCriticalSection(&mem_lock);
    mi = (mem_info_t*) HeapAlloc(mem_heap, 0, sizeof(mem_info_t));
    MC_ASSERT(mi != NULL);
    mi->next = mem_hashtable[MEM_HASHTABLE_INDEX(mem)];
    mem_hashtable[MEM_HASHTABLE_INDEX(mem)] = mi;
    mi->mem = mem;
    mi->size = size;
    mi->fname = fname;
    mi->line = line;
    LeaveCriticalSection(&mem_lock);

    DEBUG_TRACE("%s:%d: \tdebug_malloc(%lu) -> %p", fname, line, mi->size, mem);
    return mem;
}
コード例 #8
0
/* We dig into the raw resources instead of using LoadStringW() with nBufferMax
 * set to zero.
 *
 * See http://blogs.msdn.com/b/oldnewthing/archive/2004/01/30/65013.aspx.
 *
 * This allows us to do two useful things:
 *  -- Verify easily the string is zero-terminated (the assertion).
 *  -- Implement a fall-back to English, as translations can be potentially
 *     incomplete.
 */
const TCHAR*
mc_str_load(UINT id)
{
#ifndef UNICODE
    #error mc_str_load() is not (yet?) implemented for ANSI build.
#endif

    const UINT lang_id[2] = { MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
                              MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT) };
    TCHAR* rsrc_id = MAKEINTRESOURCE(id/16 + 1);
    int str_num = (id & 15);
    HRSRC rsrc;
    HGLOBAL handle;
    WCHAR* str;
    UINT len;
    int i, j;

    for(i = 0; i < MC_SIZEOF_ARRAY(lang_id); i++) {
        rsrc = FindResourceEx(mc_instance, RT_STRING, rsrc_id, lang_id[i]);
        if(MC_ERR(rsrc == NULL))
            goto not_found;
        handle = LoadResource(mc_instance, rsrc);
        if(MC_ERR(handle == NULL))
            goto not_found;
        str = (WCHAR*) LockResource(handle);
        if(MC_ERR(str == NULL))
            goto not_found;

        for(j = 0; j < str_num; j++)
            str += 1 + (UINT) *str;

        len = (UINT) *str;
        if(MC_ERR(len == 0))
            goto not_found;
        str++;

        /* Verify string resources are '\0'-terminated. This is not default
         * behavior of RC.EXE as well as windres.exe. For windres.exe we need
         * to have resources in the form "foo bar\0". For RC.EXE, we need to
         * use option '/n' to terminate the strings as RC.EXE even strips final
         * '\0' from the string even when explicitly specified. */
        MC_ASSERT(str[len - 1] == L'\0');

        return str;

not_found:
        MC_TRACE("mc_str_load: String %u missing [language 0x%x].", id,
                 (DWORD)(lang_id[i] == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
                    ? LANGIDFROMLCID(GetThreadLocale()) : lang_id[i]));
    }

    return _T("");
}
コード例 #9
0
void EXCO_Directory::InitializeHook()
{
	// Hook so the directory doesn't point to 'My Documents'
	Detours::X86::DetourFunctionClass((PBYTE)0x0044C120, &GetModDirectory);

	// Current server directory
	DWORD bufferLen = GetCurrentDirectoryA(ARRAYSIZE(ourModDirectory), ourModDirectory);

	MC_ASSERT(bufferLen > 0);

	// Append the 'mods' folder path
	strcat_s(ourModDirectory, "\\mods\\");
}
コード例 #10
0
ファイル: module.c プロジェクト: mity/mctrl
static void
module_fini_modules(module_t** modules, int n)
{
    int i;

    mc_mutex_lock(&mod_mutex);
    for(i = n-1; i >= 0; i--) {
        MC_ASSERT(modules[i]->refs > 0);
        modules[i]->refs--;
        if(modules[i]->refs == 0)
            modules[i]->fn_fini();
    }
    mc_mutex_unlock(&mod_mutex);
}
コード例 #11
0
ファイル: module.c プロジェクト: clonly/mctrl
static void
module_fini_modules(module_t** modules, int n)
{
    int i;

    EnterCriticalSection(&mod_lock);
    for(i = n-1; i >= 0; i--) {
        MC_ASSERT(modules[i]->refs > 0);
        modules[i]->refs--;
        if(modules[i]->refs == 0)
            modules[i]->fn_fini();
    }
    LeaveCriticalSection(&mod_lock);
}
コード例 #12
0
ファイル: grid.c プロジェクト: UIKit0/mctrl
static void
grid_refresh(void* view, void* detail)
{
    grid_t* grid = (grid_t*) view;
    table_refresh_detail_t* rd = (table_refresh_detail_t*) detail;
    RECT rect;

    MC_ASSERT(rd != NULL);

    switch(rd->event) {
        case TABLE_CELL_CHANGED:
            if(!grid->no_redraw) {
                grid_cell_rect(grid, rd->param[0], rd->param[1], &rect);
                InvalidateRect(grid->win, &rect, TRUE);
            }
            break;

        case TABLE_REGION_CHANGED:
            if(!grid->no_redraw) {
                grid_region_rect(grid, rd->param[0], rd->param[1],
                                 rd->param[2], rd->param[3], &rect);
                InvalidateRect(grid->win, &rect, TRUE);
            }
            break;

        case TABLE_COLCOUNT_CHANGED:
            if(grid->col_widths != NULL)
                grid_alloc_col_widths(grid, grid->col_count, rd->param[1], TRUE);
            grid->col_count = rd->param[1];
            grid_setup_scrollbars(grid, TRUE);
            if(!grid->no_redraw) {
                /* TODO: optimize by invalidating minimal rect (new cols) and
                         scrolling rightmost columns */
                InvalidateRect(grid->win, NULL, TRUE);
            }
            break;

        case TABLE_ROWCOUNT_CHANGED:
            if(grid->row_heights != NULL)
                grid_alloc_row_heights(grid, grid->row_count, rd->param[1], TRUE);
            grid->row_count = rd->param[1];
            grid_setup_scrollbars(grid, TRUE);
            if(!grid->no_redraw) {
                /* TODO: optimize by invalidating minimal rect (new rows) and
                         scrolling bottommost rows */
                InvalidateRect(grid->win, NULL, TRUE);
            }
            break;
    }
}
コード例 #13
0
ファイル: debug.c プロジェクト: UIKit0/mctrl
void
debug_fini(void)
{
    int i;
    int n = 0;
    size_t size = 0;
    mem_info_t* mi;

    /* Generate report about memory leaks */
    EnterCriticalSection(&mem_lock);
    for(i = 0; i < MEM_HASHTABLE_SIZE; i++) {
        for(mi = mem_hashtable[i]; mi != NULL; mi = mi->next) {
            if(n == 0) {
                MC_TRACE("");
                MC_TRACE("debug_fini: LEAK REPORT:");
                MC_TRACE("debug_fini: --------------------------------------------------");
#ifdef _WIN64
                MC_TRACE("debug_fini: Address              Size       Where");
#else
                MC_TRACE("debug_fini: Address      Size       Where");
#endif
                MC_TRACE("debug_fini: --------------------------------------------------");
            }

#ifdef _WIN64
            MC_TRACE("debug_fini: 0x%16p   %8lu   %s:%d", mi->mem, mi->size, mi->fname, mi->line);
#else
            MC_TRACE("debug_fini: 0x%8p   %8lu   %s:%d", mi->mem, mi->size, mi->fname, mi->line);
#endif

            n++;
            size += mi->size;
        }
    }
    LeaveCriticalSection(&mem_lock);
    if(n > 0) {
        MC_TRACE("debug_fini: --------------------------------------------------");
        MC_TRACE("debug_fini: Lost %lu bytes in %d leaks.", size, n);
        MC_TRACE("");
    }

    MC_ASSERT(n == 0);

    /* Uninitialize */
    HeapDestroy(mem_heap);
    DeleteCriticalSection(&mem_lock);
}
コード例 #14
0
ファイル: viewlist.c プロジェクト: ArmstrongJ/mctrl
void
view_list_uninstall_view(view_list_t* vlist, void* view)
{
    view_node_t* node = vlist->head;
    view_node_t* prev = NULL;

    while(node->view != view) {
        MC_ASSERT(node != NULL);
        prev = node;
        node = node->next;
    }

    if(prev)
        prev->next = node->next;
    else
        vlist->head = node->next;
    free(node);
}
コード例 #15
0
ファイル: table.c プロジェクト: mity/mctrl
void
table_destroy(table_t* table)
{
    TABLE_TRACE("table_destroy(%p)", table);
    MC_ASSERT(table->refs == 0);

    if(table->cells) {
        int i, n;

        n = table->col_count + table->row_count + table->col_count * table->row_count;
        for(i = 0; i < n; i++)
            table_cell_clear(&table->cells[i]);

        free(table->cells);
    }

    view_list_fini(&table->vlist);
    free(table);
}
コード例 #16
0
ファイル: viewlist.c プロジェクト: ArmstrongJ/mctrl
int
view_list_install_view(view_list_t* vlist, void* view, view_refresh_t refresh)
{
    view_node_t* node;

    /* View can be installed only once in the list */
#ifdef DEBUG
    for(node = vlist->head; node != NULL; node = node->next)
        MC_ASSERT(node->view != view);
#endif

    node = (view_node_t*) malloc(sizeof(view_node_t));
    if(MC_ERR(node == NULL)) {
        MC_TRACE("view_install: malloc() failed.");
        return -1;
    }

    node->view = view;
    node->refresh = refresh;
    node->next = vlist->head;
    vlist->head = node;
    return 0;
}
コード例 #17
0
ファイル: button.c プロジェクト: ArmstrongJ/mctrl
static void
button_paint_icon(HWND win, button_t* button, HDC dc)
{
    HICON icon;
    RECT rect;
    RECT content;
    int state;
    SIZE size;
    UINT flags;
    HFONT font, old_font;
    int old_bk_mode;
    COLORREF old_text_color;
    HRGN old_clip;

    /* When theming is not used, we keep all the work on COMCTL32 button
     * implementation. */
    MC_ASSERT(button->theme != NULL);

    GetClientRect(win, &rect);

    icon = (HICON) MC_SEND(win, BM_GETIMAGE, IMAGE_ICON, 0);
    font = (HFONT) MC_SEND(win, WM_GETFONT, 0, 0);
    if(font == NULL)
        font = GetStockObject(SYSTEM_FONT);

    old_font = SelectObject(dc, font);
    old_bk_mode = GetBkMode(dc);
    old_text_color = GetTextColor(dc);
    old_clip = get_clip(dc);

    /* Draw background */
    if(button->style & WS_DISABLED) {
        state = PBS_DISABLED;
    } else {
        LRESULT s = MC_SEND(win, BM_GETSTATE, 0, 0);
        if(s & BST_PUSHED)
            state = PBS_PRESSED;
        else if(s & BST_HOT)
            state = PBS_HOT;
        else if(button->style & BS_DEFPUSHBUTTON)
            state = PBS_DEFAULTED;
        else
            state = PBS_NORMAL;
    }
    if(mcIsThemeBackgroundPartiallyTransparent(button->theme, BP_PUSHBUTTON, state))
        mcDrawThemeParentBackground(win, dc, &rect);
    mcDrawThemeBackground(button->theme, dc, BP_PUSHBUTTON, state, &rect, &rect);

    /* Get content rectangle of the button and clip DC to it */
    mcGetThemeBackgroundContentRect(button->theme, dc, BP_PUSHBUTTON, state, &rect, &content);
    IntersectClipRect(dc, content.left, content.top, content.right, content.bottom);

    /* Draw focus rectangle */
    if(MC_SEND(win, BM_GETSTATE, 0, 0) & BST_FOCUS) {
        if(!button->hide_focus)
            DrawFocusRect(dc, &content);
    }

    /* Draw the contents (i.e. the icon) */
    if(icon != NULL) {
        mc_icon_size(icon, &size);
        flags = DST_ICON;
        if(button->style & WS_DISABLED)
            flags |= DSS_DISABLED;
        DrawState(dc, NULL, NULL, (LPARAM) icon, 0, (rect.right + rect.left - size.cx) / 2,
                  (rect.bottom + rect.top - size.cy) / 2, size.cx, size.cy, flags);
    }

    /* Revert DC into original state */
    SelectObject(dc, old_font);
    SetBkMode(dc, old_bk_mode);
    SetTextColor(dc, old_text_color);
    SelectObject(dc, old_clip);
}
コード例 #18
0
ファイル: table.c プロジェクト: mity/mctrl
static int
table_resize_helper(table_t* table, int col_pos, int col_delta,
                                    int row_pos, int row_delta)
{
    size_t size;
    table_cell_t* cols;
    table_cell_t* rows;
    table_cell_t* cells;
    table_region_t copy_src[4];
    table_region_t copy_dst[4];
    table_region_t init_dst[3];
    table_region_t free_src[3];
    int copy_count, init_count, free_count;
    int col_count, row_count;
    int i;
    table_refresh_detail_t refresh_detail;

    TABLE_TRACE("table_resize_helper(%p, %d, %d, %d, %d)",
                table, col_pos, col_delta, row_pos, row_delta);

    if(col_delta == 0  &&  row_delta == 0) {
        /* noop */
        return 0;
    }

    col_count = table->col_count + col_delta;
    row_count = table->row_count + row_delta;

    if(col_delta == 0)
        col_pos = col_count;
    if(row_delta == 0)
        row_pos = row_count;

    /* Allocate buffer for resized table */
    size = col_count * sizeof(table_cell_t) +
           row_count * sizeof(table_cell_t) +
           (col_count*row_count) * sizeof(table_cell_t);
    if(size > 0) {
        cells = (table_cell_t*) malloc(size);
        if(MC_ERR(cells == NULL)) {
            MC_TRACE("table_resize: malloc() failed");
            return -1;
        }

        cols = cells + (col_count * row_count);
        rows = cols + col_count;
    } else {
        cells = NULL;
        cols = NULL;
        rows = NULL;
    }

    /* Analyze which region of the original cells shall be freed, which shall
     * be reused in the reallocated buffer, and which in the new buffer need
     * initialization. */
#define REGSET(reg, c0, r0, c1, r1)                                           \
            do { reg.col0 = c0; reg.row0 = r0;                                \
                 reg.col1 = c1; reg.row1 = r1; } while (0)
    if(col_delta >= 0  &&  row_delta >= 0) {
        /*
         *                     +---+-+---+
         *    +---+---+        | 0 | | 1 |
         *    | 0 | 1 |        +---+-+---+
         *    +---+---+  --->  |         |
         *    | 2 | 3 |        +---+-+---+
         *    +---+---+        | 2 | | 3 |
         *                     +---+-+---+
         */
        REGSET(copy_src[0], 0, 0, col_pos, row_pos);
        REGSET(copy_dst[0], 0, 0, col_pos, row_pos);
        REGSET(copy_src[1], col_pos, 0, table->col_count, row_pos);
        REGSET(copy_dst[1], col_pos + col_delta, 0, col_count, row_pos);
        REGSET(copy_src[2], 0, row_pos, col_pos, table->row_count);
        REGSET(copy_dst[2], 0, row_pos + row_delta, col_pos, row_count);
        REGSET(copy_src[3], col_pos, row_pos, table->col_count, table->row_count);
        REGSET(copy_dst[3], col_pos + col_delta, row_pos + row_delta, col_count, row_count);
        copy_count = 4;
        REGSET(init_dst[0], col_pos, 0, col_pos + col_delta, row_pos);
        REGSET(init_dst[1], 0, row_pos, col_count, row_pos + row_delta);
        REGSET(init_dst[2], col_pos, row_pos + row_delta, col_pos + col_delta, row_count);
        init_count = 3;
        free_count = 0;
    } else if(col_delta >= 0  &&  row_delta < 0) {
        /*
         *    +---+---+
         *    | 0 | 1 |        +---+-+---+
         *    +---+---+        | 0 | | 1 |
         *    |       |  --->  +---+ +---+
         *    +---+---+        | 2 | | 3 |
         *    | 2 | 3 |        +---+-+---+
         *    +---+---+
         */
        REGSET(copy_src[0], 0, 0, col_pos, row_pos);
        REGSET(copy_dst[0], 0, 0, col_pos, row_pos);
        REGSET(copy_src[1], col_pos, 0, table->col_count, row_pos);
        REGSET(copy_dst[1], col_pos + col_delta, 0, col_count, row_pos);
        REGSET(copy_src[2], 0, row_pos - row_delta, col_pos, table->row_count);
        REGSET(copy_dst[2], 0, row_pos, col_pos, row_count);
        REGSET(copy_src[3], col_pos, row_pos - row_delta, table->col_count, table->row_count);
        REGSET(copy_dst[3], col_pos + col_delta, row_pos, col_count, row_count);
        copy_count = 4;
        REGSET(init_dst[0], col_pos, 0, col_pos + col_delta, row_count);
        init_count = 1;
        REGSET(free_src[0], 0, row_pos, table->col_count, row_pos - row_delta);
        free_count = 1;
    } else if(col_delta < 0  &&  row_delta >= 0) {
        /*
         *                       +---+---+
         *    +---+-+---+        | 0 | 1 |
         *    | 0 | | 1 |        +---+---+
         *    +---+ +---+  --->  |       |
         *    | 2 | | 3 |        +---+---+
         *    +---+-+---+        | 2 | 3 |
         *                       +---+---+
         */
        REGSET(copy_src[0], 0, 0, col_pos, row_pos);
        REGSET(copy_dst[0], 0, 0, col_pos, row_pos);
        REGSET(copy_src[1], col_pos - col_delta, 0, table->col_count, row_pos);
        REGSET(copy_dst[1], col_pos, 0, col_count, row_pos);
        REGSET(copy_src[2], 0, row_pos, col_pos, table->row_count);
        REGSET(copy_dst[2], 0, row_pos + row_delta, col_pos, row_count);
        REGSET(copy_src[3], col_pos - col_delta, row_pos, table->col_count, table->row_count);
        REGSET(copy_dst[3], col_pos, row_pos + row_delta, col_count, row_count);
        copy_count = 4;
        REGSET(init_dst[0], 0, row_pos, col_count, row_pos + row_delta);
        init_count = 1;
        REGSET(free_src[0], col_pos, 0, col_pos - col_delta, table->row_count);
        free_count = 1;
    } else {
        MC_ASSERT(col_delta < 0  &&  row_delta < 0);
        /*
         *    +---+-+---+
         *    | 0 | | 1 |        +---+---+
         *    +---+-+---+        | 0 | 1 |
         *    |         |  --->  +---+---+
         *    +---+-+---+        | 2 | 3 |
         *    | 2 | | 3 |        +---+---+
         *    +---+-+---+
         */
        REGSET(copy_src[0], 0, 0, col_pos, row_pos);
        REGSET(copy_dst[0], 0, 0, col_pos, row_pos);
        REGSET(copy_src[1], col_pos - col_delta, 0, table->col_count, row_pos);
        REGSET(copy_dst[1], col_pos, 0, col_count, row_pos);
        REGSET(copy_src[2], 0, row_pos - row_delta, col_pos, table->row_count);
        REGSET(copy_dst[2], 0, row_pos, col_pos, row_count);
        REGSET(copy_src[3], col_pos - col_delta, row_pos - row_delta, table->col_count, table->row_count);
        REGSET(copy_dst[3], col_pos, row_pos, col_count, row_count);
        copy_count = 4;
        init_count = 0;
        REGSET(free_src[0], col_pos, 0, col_pos - col_delta, row_pos);
        REGSET(free_src[1], 0, row_pos, table->col_count, row_pos - row_delta);
        REGSET(free_src[2], col_pos, row_pos - row_delta, col_pos - col_delta, table->row_count);
        free_count = 3;
    }
#undef REGSET

    /* Copy cells to be reused */
    if(table->cells != NULL  &&  cells != NULL) {
        for(i = 0; i < copy_count; i++) {
            MC_ASSERT(copy_src[i].col1-copy_src[i].col0 == copy_dst[i].col1-copy_dst[i].col0);
            MC_ASSERT(copy_src[i].row1-copy_src[i].row0 == copy_dst[i].row1-copy_dst[i].row0);

            if(col_delta == 0) {
                memcpy(&cells[copy_dst[i].row0 * col_count],
                       &table->cells[copy_src[i].row0 * col_count],
                       (copy_src[i].row1-copy_src[i].row0) * (copy_src[i].col1-copy_src[i].col0) * sizeof(table_cell_t));
            } else {
                WORD row_src, row_dst;
                for(row_src = copy_src[i].row0, row_dst = copy_dst[i].row0;
                            row_src < copy_src[i].row1; row_src++, row_dst++) {
                    memcpy(&cells[row_dst * col_count + copy_dst[i].col0],
                           &table->cells[row_src * table->col_count + copy_src[i].col0],
                           (copy_src[i].col1-copy_src[i].col0) * sizeof(table_cell_t));
                }
            }
        }
    }

    /* Init new cells in the new buffer */
    if(cells != NULL) {
        for(i = 0; i < init_count; i++) {
            if(col_delta == 0) {
                memset(&cells[col_count * init_dst[i].row0], 0,
                       col_count * (init_dst[i].row1-init_dst[i].row0) * sizeof(table_cell_t));
            } else {
                WORD row;
                for(row = init_dst[i].row0; row < init_dst[i].row1; row++) {
                    memset(&cells[row * col_count + init_dst[i].col0], 0,
                           (init_dst[i].col1-init_dst[i].col0) * sizeof(table_cell_t));
                }
            }
        }
    }

    /* Free bogus cells in the old buffer */
    if(table->cells != NULL) {
        for(i = 0; i < free_count; i++) {
            WORD col, row;
            for(row = free_src[i].row0; row < free_src[i].row1; row++) {
                for(col = free_src[i].col0; col < free_src[i].col1; col++) {
                    table_cell_clear(&table->cells[row * table->col_count + col]);
                }
            }
        }
    }

    /* Handle column headers */
    if(cols != NULL  &&  table->cols != NULL) {
        memcpy(&cols[0], &table->cols[0], col_pos * sizeof(table_cell_t));
        if(col_delta > 0)
            memcpy(&cols[col_pos + col_delta], &table->cols[col_pos],
                   (table->col_count - col_pos) * sizeof(table_cell_t));
        else if(col_delta < 0)
            memcpy(&cols[col_pos], &table->cols[col_pos - col_delta],
                   (col_count - col_pos) * sizeof(table_cell_t));
    }
    if(cols != NULL  &&  col_delta > 0)
        memset(&cols[col_pos], 0, col_delta * sizeof(table_cell_t));
    if(table->cols != NULL  &&  col_delta < 0) {
        WORD col;
        for(col = col_pos; col < col_pos - col_delta; col++)
            table_cell_clear(&table->cols[col]);
    }

    /* Handle row headers */
    if(rows != NULL  &&  table->rows != NULL) {
        memcpy(&rows[0], &table->rows[0], row_pos * sizeof(table_cell_t));
        if(row_delta > 0)
            memcpy(&rows[row_pos + row_delta], &table->rows[row_pos],
                   (table->row_count - row_pos) * sizeof(table_cell_t));
        else if(row_delta < 0)
            memcpy(&rows[row_pos], &table->rows[row_pos - row_delta],
                   (row_count - row_pos) * sizeof(table_cell_t));
    }
    if(rows != NULL  &&  row_delta > 0)
        memset(&rows[row_pos], 0, row_delta * sizeof(table_cell_t));
    if(table->rows != NULL  &&  row_delta < 0) {
        WORD row;
        for(row = row_pos; row < row_pos - row_delta; row++)
            table_cell_clear(&table->rows[row]);
    }

    /* Install the new buffer */
    if(table->cells != NULL)
        free(table->cells);
    table->cols = cols;
    table->rows = rows;
    table->cells = cells;
    table->col_count = col_count;
    table->row_count = row_count;

    /* Refresh */
    if(col_delta != 0) {
        refresh_detail.event = TABLE_COLCOUNT_CHANGED;
        refresh_detail.param[0] = table->col_count - col_delta;
        refresh_detail.param[1] = table->col_count;
        refresh_detail.param[2] = col_pos;
        table_refresh(table, &refresh_detail);
    }
    if(row_delta != 0) {
        refresh_detail.event = TABLE_ROWCOUNT_CHANGED;
        refresh_detail.param[0] = table->row_count - row_delta;
        refresh_detail.param[1] = table->row_count;
        refresh_detail.param[2] = row_pos;
        table_refresh(table, &refresh_detail);
    }

    return 0;
}
コード例 #19
0
ファイル: menubar.c プロジェクト: Strongc/mctrl
static LRESULT CALLBACK
menubar_ht_proc(int code, WPARAM wp, LPARAM lp)
{
    if(code >= 0) {
        MSG* msg = (MSG*)lp;
        menubar_t* mb = menubar_ht_mb;

        MC_ASSERT(mb != NULL);

        switch(msg->message) {
            case WM_MENUSELECT:
                menubar_ht_sel_menu = (HMENU)msg->lParam;
                menubar_ht_sel_item = LOWORD(msg->wParam);
                menubar_ht_sel_flags = HIWORD(msg->wParam);
                MENUBAR_TRACE("menubar_ht_proc: WM_MENUSELECT %p %d", menubar_ht_sel_menu, menubar_ht_sel_item);
                break;

            case WM_MOUSEMOVE:
            {
                POINT pt = msg->pt;
                int item;

                MapWindowPoints(NULL, mb->win, &pt, 1);
                item = MENUBAR_SENDMSG(mb->win, TB_HITTEST, 0, (LPARAM)&pt);
                if(menubar_ht_last_pos.x != pt.x  ||  menubar_ht_last_pos.y != pt.y) {
                    menubar_ht_last_pos = pt;
                    if(item != mb->pressed_item  &&
                       0 <= item  &&  item < MENUBAR_SENDMSG(mb->win, TB_BUTTONCOUNT, 0, 0)) {
                        MENUBAR_TRACE("menubar_ht_proc: Change dropdown by mouse move "
                                      "[%d -> %d]", mb->pressed_item, item);
                        menubar_ht_change_dropdown(mb, item, FALSE);
                    }
                }
                break;
            }

            case WM_KEYDOWN:
            case WM_SYSKEYDOWN:
                switch(msg->wParam) {
                    case VK_MENU:
                    case VK_F10:
                        menubar_ht_change_dropdown(mb, -1, TRUE);
                        return 0;

                    case VK_LEFT:
                        if(menubar_ht_sel_menu == NULL  ||
                           menubar_ht_sel_menu == GetSubMenu(mb->menu, mb->pressed_item))
                        {
                            int item = mb->pressed_item - 1;
                            if(item < 0)
                                item = MENUBAR_SENDMSG(mb->win, TB_BUTTONCOUNT, 0, 0) - 1;
                            MENUBAR_TRACE("menubar_ht_proc: Change dropdown by VK_LEFT");
                            if(item != mb->pressed_item)
                                menubar_ht_change_dropdown(mb, item, TRUE);
                            menubar_update_ui_state(mb, TRUE);
                        }
                        break;

                    case VK_RIGHT:
                        if(menubar_ht_sel_menu == NULL  ||
                           !(menubar_ht_sel_flags & MF_POPUP) ||
                           (menubar_ht_sel_flags & (MF_GRAYED | MF_DISABLED)))
                        {
                            int item = mb->pressed_item + 1;
                            if(item >= MENUBAR_SENDMSG(mb->win, TB_BUTTONCOUNT, 0, 0))
                                item = 0;
                            MENUBAR_TRACE("menubar_ht_proc: Change dropdown by VK_RIGHT");
                            if(item != mb->pressed_item)
                                menubar_ht_change_dropdown(mb, item, TRUE);
                            menubar_update_ui_state(mb, TRUE);
                        }
                        break;
                }
                break;
        }
    }

    return CallNextHookEx(menubar_ht_hook, code, wp, lp);
}
コード例 #20
0
ファイル: grid.c プロジェクト: UIKit0/mctrl
static void
grid_get_dispinfo(grid_t* grid, WORD col, WORD row, table_cell_t* cell,
                  grid_dispinfo_t* di, DWORD mask)
{
    MC_NMGDISPINFO info;

    MC_ASSERT((mask & ~(MC_TCMF_TEXT | MC_TCMF_VALUE | MC_TCMF_FLAGS)) == 0);

    /* Use what can be taken from the cell. */
    if(cell != NULL) {
        if(cell->text != MC_LPSTR_TEXTCALLBACK) {
            di->text = (cell->is_value ? NULL : cell->text);
            mask &= ~MC_TCMF_TEXT;
        }

        di->value = (cell->is_value ? cell->value : NULL);
        di->flags = cell->flags;
        mask &= ~(MC_TCMF_VALUE | MC_TCMF_FLAGS);

        if(mask == 0)
            return;
    }

    /* For the rest data, fire MC_GN_GETDISPINFO notification. */
    info.hdr.hwndFrom = grid->win;
    info.hdr.idFrom = GetWindowLong(grid->win, GWL_ID);
    info.hdr.code = (grid->unicode_notifications ? MC_GN_GETDISPINFOW : MC_GN_GETDISPINFOA);
    info.wColumn = col;
    info.wRow = row;
    info.cell.fMask = mask;
    /* Set info.cell members to meaningful values. lParam may be needed by the
     * app to find the requested data. Other members should be set to some
     * defaults to deal with broken apps which do not set the asked members. */
    if(cell != NULL) {
        info.cell.pszText = NULL;
        info.cell.hValue = NULL;
        info.cell.lParam = cell->lp;
        info.cell.dwFlags = cell->flags;
    } else {
        info.cell.pszText = NULL;
        info.cell.hValue = NULL;
        info.cell.lParam = 0;
        info.cell.dwFlags = 0;
    }
    MC_SEND(grid->notify_win, WM_NOTIFY, 0, &info);

    /* If needed, convert the text from parent to the expected format. */
    if(mask & MC_TCMF_TEXT) {
        if(grid->unicode_notifications == MC_IS_UNICODE)
            di->text = info.cell.pszText;
        else
            di->text = mc_str(info.cell.pszText, (grid->unicode_notifications ? MC_STRW : MC_STRA), MC_STRT);
    } else {
        /* Needed even when not asked for because of grid_free_dispinfo() */
        di->text = NULL;
    }

    /* Small optimization: We do not ask about the corresponding bits in the
     * mask for these. If not set, the assignment does no hurt and we save few
     * instructions. */
    di->value = info.cell.hValue;
    di->flags = info.cell.dwFlags;
}
コード例 #21
0
ファイル: debug.c プロジェクト: UIKit0/mctrl
void
debug_free(const char* fname, int line, void* mem)
{
    mem_info_t* mi_prev = NULL;
    mem_info_t* mi;
    BYTE* head;
    BYTE* tail;

    MC_ASSERT(mem != NULL);

    EnterCriticalSection(&mem_lock);

    /* Find memory info for the memory chunk */
    mi = mem_hashtable[MEM_HASHTABLE_INDEX(mem)];
    while(TRUE) {
        if(MC_ERR(mi == NULL)) {
            /* Not registered? */
            MC_TRACE("%s:%d: \tdebug_free(%p): Attempting to release "
                     "non-allocated memory.", fname, line, mem);
            MC_ASSERT(1 == 0);
        }

        if(mi->mem == mem)
            break;

        mi_prev = mi;
        mi = mi->next;
    }

    DEBUG_TRACE("%s:%d: \tdebug_free(%p) [size=%lu]", fname, line, mem, mi->size);

    /* Check that the over/underrun guards are intact */
    head = ((BYTE*)mem) - sizeof(head_guard);
    tail = ((BYTE*)mem) + mi->size;
    if(memcmp(head, head_guard, sizeof(head_guard)) != 0) {
        MC_TRACE("%s:%d: \tdebug_free(%p) detected buffer underrun "
                 "[guard={%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x}, "
                 "size=%lu]. Was allocated here: %s:%d",
                 fname, line, mem,
                 head[0], head[1], head[2], head[3], head[4], head[5], head[6], head[7],
                 head[8], head[9], head[10], head[11], head[12], head[13], head[14], head[15],
                 mi->size, mi->fname, mi->line);
        MC_ASSERT(2 == 0);
    }
    if(memcmp(tail, tail_guard, sizeof(tail_guard)) != 0) {
        MC_TRACE("%s:%d: \tdebug_free(%p) detected buffer overrun "
                 "[guard={%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x}, "
                 "size=%lu]. Was allocated here: %s:%d",
                 fname, line, mem,
                 tail[0], tail[1], tail[2], tail[3], tail[4], tail[5], tail[6], tail[7],
                 tail[8], tail[9], tail[10], tail[11], tail[12], tail[13], tail[14], tail[15],
                 mi->size, mi->fname, mi->line);
        MC_ASSERT(3 == 0);
    }

    /* Rewrite all the memory with 'invalid-memory' mark, including the guards.
     * (this can help to debug (mis)uses of released memory) */
    memset(head, 0xee, mi->size + 2 * sizeof(head_guard));

    /* Unregister the memory info */
    if(mi_prev != NULL)
        mi_prev->next = mi->next;
    else
        mem_hashtable[MEM_HASHTABLE_INDEX(mem)] = mi->next;
    HeapFree(mem_heap, 0, mi);

    LeaveCriticalSection(&mem_lock);

    /* Finally we can free it */
    free(head);
}