int table_set_cell_data(table_t* table, WORD col, WORD row, MC_TABLECELL* cell_data, BOOL unicode) { table_cell_t* cell; table_refresh_detail_t refresh_detail; TABLE_TRACE("table_set_cell_data(%p, %hd, %hd, %p, %s)", table, col, row, cell_data, (unicode ? "unicode" : "ansi")); cell = table_get_cell(table, col, row); if(MC_ERR(cell == NULL)) { MC_TRACE("table_set_cell_data: table_get_cell() failed."); return -1; } if(MC_ERR(cell_data->fMask & ~MC_TCMF_ALL)) { MC_TRACE("table_set_cell_data: Unsupported pCell->fMask 0x%x", cell_data->fMask); SetLastError(ERROR_INVALID_PARAMETER); return -1; } /* Set the cell */ if(cell_data->fMask & MC_TCMF_TEXT) { TCHAR* str; if(cell_data->pszText == MC_LPSTR_TEXTCALLBACK) { str = MC_LPSTR_TEXTCALLBACK; } else if(cell_data->pszText != NULL) { str = mc_str(cell_data->pszText, (unicode ? MC_STRW : MC_STRA), MC_STRT); if(MC_ERR(str == NULL)) { MC_TRACE("table_set_cell_data: mc_str() failed."); return -1; } } else { str = NULL; } table_cell_clear(cell); cell->text = str; } if(cell_data->fMask & MC_TCMF_PARAM) cell->lp = cell_data->lParam; if(cell_data->fMask & MC_TCMF_FLAGS) cell->flags = cell_data->dwFlags; /* Refresh */ refresh_detail.event = TABLE_CELL_CHANGED; refresh_detail.param[0] = col; refresh_detail.param[1] = row; table_refresh(table, &refresh_detail); return 0; }
int table_get_cell_data(table_t* table, WORD col, WORD row, MC_TABLECELL* cell_data, BOOL unicode) { table_cell_t* cell; TABLE_TRACE("table_get_cell_data(%p, %hd, %hd, %p, %s)", table, col, row, cell_data, (unicode ? "unicode" : "ansi")); cell = table_get_cell(table, col, row); if(MC_ERR(cell == NULL)) { MC_TRACE("table_set_cell_data: table_get_cell_data() failed."); return -1; } if(MC_ERR(cell_data->fMask & ~MC_TCMF_ALL)) { MC_TRACE("table_get_cell_data: Unsupported pCell->fMask 0x%x", cell_data->fMask); SetLastError(ERROR_INVALID_PARAMETER); return -1; } if(cell_data->fMask & MC_TCMF_TEXT) { if(cell->text == MC_LPSTR_TEXTCALLBACK) { MC_TRACE("table_get_cell_data: Table cell contains " "MC_LPSTR_TEXTCALLBACK and that cannot be asked for."); SetLastError(ERROR_INVALID_PARAMETER); return -1; } else { mc_str_inbuf(cell->text, MC_STRT, cell_data->pszText, (unicode ? MC_STRW : MC_STRA), cell_data->cchTextMax); } } if(cell_data->fMask & MC_TCMF_PARAM) cell_data->lParam = cell->lp; if(cell_data->fMask & MC_TCMF_FLAGS) cell_data->dwFlags = cell->flags; return 0; }
/* Creates and returns a new render_page for rendering TABLE on a device described by PARAMS. The new render_page will be suitable for rendering on a device whose page size is PARAMS->size, but the caller is responsible for actually breaking it up to fit on such a device, using the render_break abstraction. */ struct render_page * render_page_create (const struct render_params *params, const struct table *table_) { struct render_page *page; struct table *table; enum { MIN, MAX }; struct render_row *columns[2]; struct render_row *rows; int table_widths[2]; int *rules[TABLE_N_AXES]; int nr, nc; int x, y; int i; enum table_axis axis; table = table_ref (table_); nc = table_nc (table); nr = table_nr (table); /* Figure out rule widths. */ for (axis = 0; axis < TABLE_N_AXES; axis++) { int n = table->n[axis] + 1; int z; rules[axis] = xnmalloc (n, sizeof *rules); for (z = 0; z < n; z++) rules[axis][z] = measure_rule (params, table, axis, z); } /* Calculate minimum and maximum widths of cells that do not span multiple columns. */ for (i = 0; i < 2; i++) columns[i] = xzalloc (nc * sizeof *columns[i]); for (y = 0; y < nr; y++) for (x = 0; x < nc; ) { struct table_cell cell; table_get_cell (table, x, y, &cell); if (y == cell.d[V][0] && table_cell_colspan (&cell) == 1) { int w[2]; int i; params->measure_cell_width (params->aux, &cell, &w[MIN], &w[MAX]); for (i = 0; i < 2; i++) if (columns[i][x].unspanned < w[i]) columns[i][x].unspanned = w[i]; } x = cell.d[H][1]; table_cell_free (&cell); } /* Distribute widths of spanned columns. */ for (i = 0; i < 2; i++) for (x = 0; x < nc; x++) columns[i][x].width = columns[i][x].unspanned; for (y = 0; y < nr; y++) for (x = 0; x < nc; ) { struct table_cell cell; table_get_cell (table, x, y, &cell); if (y == cell.d[V][0] && table_cell_colspan (&cell) > 1) { int w[2]; params->measure_cell_width (params->aux, &cell, &w[MIN], &w[MAX]); for (i = 0; i < 2; i++) distribute_spanned_width (w[i], &columns[i][cell.d[H][0]], rules[H], table_cell_colspan (&cell)); } x = cell.d[H][1]; table_cell_free (&cell); } /* Decide final column widths. */ for (i = 0; i < 2; i++) table_widths[i] = calculate_table_width (table_nc (table), columns[i], rules[H]); if (table_widths[MAX] <= params->size[H]) { /* Fits even with maximum widths. Use them. */ page = create_page_with_exact_widths (params, table, columns[MAX], rules[H]); } else if (table_widths[MIN] <= params->size[H]) { /* Fits with minimum widths, so distribute the leftover space. */ page = create_page_with_interpolated_widths ( params, table, columns[MIN], columns[MAX], table_widths[MIN], table_widths[MAX], rules[H]); } else { /* Doesn't fit even with minimum widths. Assign minimums for now, and later we can break it horizontally into multiple pages. */ page = create_page_with_exact_widths (params, table, columns[MIN], rules[H]); } /* Calculate heights of cells that do not span multiple rows. */ rows = xzalloc (nr * sizeof *rows); for (y = 0; y < nr; y++) { for (x = 0; x < nc; ) { struct render_row *r = &rows[y]; struct table_cell cell; table_get_cell (table, x, y, &cell); if (y == cell.d[V][0]) { if (table_cell_rowspan (&cell) == 1) { int w = joined_width (page, H, cell.d[H][0], cell.d[H][1]); int h = params->measure_cell_height (params->aux, &cell, w); if (h > r->unspanned) r->unspanned = r->width = h; } else set_join_crossings (page, V, &cell, rules[V]); if (table_cell_colspan (&cell) > 1) set_join_crossings (page, H, &cell, rules[H]); } x = cell.d[H][1]; table_cell_free (&cell); } } for (i = 0; i < 2; i++) free (columns[i]); /* Distribute heights of spanned rows. */ for (y = 0; y < nr; y++) for (x = 0; x < nc; ) { struct table_cell cell; table_get_cell (table, x, y, &cell); if (y == cell.d[V][0] && table_cell_rowspan (&cell) > 1) { int w = joined_width (page, H, cell.d[H][0], cell.d[H][1]); int h = params->measure_cell_height (params->aux, &cell, w); distribute_spanned_width (h, &rows[cell.d[V][0]], rules[V], table_cell_rowspan (&cell)); } x = cell.d[H][1]; table_cell_free (&cell); } /* Decide final row heights. */ accumulate_row_widths (page, V, rows, rules[V]); free (rows); /* Measure headers. If they are "too big", get rid of them. */ for (axis = 0; axis < TABLE_N_AXES; axis++) { int hw = headers_width (page, axis); if (hw * 2 >= page->params->size[axis] || hw + max_cell_width (page, axis) > page->params->size[axis]) { page->table = table_unshare (page->table); page->table->h[axis][0] = page->table->h[axis][1] = 0; page->h[axis][0] = page->h[axis][1] = 0; } } free (rules[H]); free (rules[V]); return page; }