From 61ac2051c82c9d6f0e67e6efdfcb66b5a8d98070 Mon Sep 17 00:00:00 2001 From: Nicholas Todoroff Date: Thu, 17 Aug 2023 15:48:30 -0600 Subject: Handle tabs in :ccopy consistently Only output tabs when conf_clipboard_delimited_tab is set to 1, and only pad with spaces when set to 0. --- src/clipboard.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/clipboard.c b/src/clipboard.c index 2ca7fc9..94d8636 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -261,12 +261,15 @@ int save_plain(FILE * fout, int r0, int c0, int rn, int cn) { else { emptyfield++; } - if(emptyfield){ - fwprintf(fout, L"\t"); - } if (! conf_clipboard_delimited_tab) { - pad_and_align(text, num, roman->cur_sh->fwidth[col], align, 0, out, roman->cur_sh->row_format[row]); - fwprintf(fout, L"%ls", out); + if (emptyfield) { + fwprintf(fout, L"%*s", roman->cur_sh->fwidth[col], " "); + } else { + pad_and_align(text, num, roman->cur_sh->fwidth[col], align, 0, out, roman->cur_sh->row_format[row]); + fwprintf(fout, L"%ls", out); + } + } else if (emptyfield){ + fwprintf(fout, L"\t"); } else if ( (*pp)->flags & is_valid) { fwprintf(fout, L"%s\t", num); } else if ( (*pp)->label) { -- cgit v1.2.3 From e1fdb425b63cb121c6e7c332f621941b81dcf74a Mon Sep 17 00:00:00 2001 From: Nicholas Todoroff Date: Thu, 17 Aug 2023 18:35:55 -0600 Subject: Allow :ccopy to copy full representation of cells Adds a configuration variable "copy_to_clipboard_wysiwyg" which defaults to 1. When this variable is nonzero, :ccopy copies the selected range as it's displayed. When set to zero, :ccopy copies a full string representation of the cells. --- src/clipboard.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/conf.c | 1 + src/doc | 6 ++++++ src/gram.y | 8 ++++++- 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/clipboard.c b/src/clipboard.c index 94d8636..e08c74d 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -204,16 +204,74 @@ int save_plain(FILE * fout, int r0, int c0, int rn, int cn) { if (fout == NULL) return -1; struct roman * roman = session->cur_doc; int conf_clipboard_delimited_tab = get_conf_int("copy_to_clipboard_delimited_tab"); - int row, col; + int conf_clipboard_wysiwyg = get_conf_int("copy_to_clipboard_wysiwyg"); + int row, col, test_width; + struct ent * p; register struct ent ** pp; + mbstate_t state; wchar_t out[FBUFLEN] = L""; + const char *label = NULL; char num [FBUFLEN] = ""; char text[FBUFLEN] = ""; char formated_s[FBUFLEN] = ""; int res = -1; int align = 1; int emptyfield=-1; + int out_widths[cn - c0 + 1]; + // Calculates the column widths necessary to output. + // If copy_to_clipboard_delimited_tab != 0 then we don't need any of this. + // If copy_to_clipboard_wysiwyg != 0 + // then just use roman->cur_sh->fwidths[col]. + // Otherwise, if the data already fits inside roman->cur_sh->fwidths[col] + // then that is the width used. + // If it doesn't + // then we use the largest data width found in the column and add 1. + if (!conf_clipboard_delimted_tab) { + for (col = c0; col <= cn; ++col) { + out_widths[col-c0] = roman->cur_sh->fwidth[col]; + if (!conf_clipboard_wysiwyg) { + for (row = r0; row <= rn; ++row) { + p = *ATBL(roman->cur_sh, roman->cur_sh->tbl, row, col); + if (!p || p->flags & is_deleted) continue; + if (p->flags & is_valid) { + num[0] = '\0'; + formated_s[0] = '\0'; + res = ui_get_formated_value(&p, col, formated_s); + // res = 0, indicates that in num we store a date + // res = 1, indicates a format is applied in num + if (res == 0 || res == 1) { + strcpy(num, formated_s); + } else if (res == -1) { + sprintf(num, "%.*f", roman->cur_sh->precision[col], p->v); + } + test_width = strlen(num); + } + else if (p->label) { + // Calculate the display width of p->label. + memset(&state, '\0', sizeof state); + label = p->label; + res = mbsrtowcs(out, &label, FBUFLEN, &state); + if (res != (size_t)-1) + test_width = wcswidth(out, wcslen(out)); + else { + test_width = 0; + sc_error("Failed to convert cell label to wide string"); + } + } + else { + test_width = 0; + } + + if (test_width >= out_widths[col-c0]) { + out_widths[col-c0] = test_width + 1; + } + } + } + } + } + + res = -1; for (row = r0; row <= rn; row++) { // ignore hidden rows //if (row_hidden[row]) continue; @@ -261,11 +319,12 @@ int save_plain(FILE * fout, int r0, int c0, int rn, int cn) { else { emptyfield++; } + if (! conf_clipboard_delimited_tab) { if (emptyfield) { - fwprintf(fout, L"%*s", roman->cur_sh->fwidth[col], " "); + fwprintf(fout, L"%*s", out_widths[col-c0], " "); } else { - pad_and_align(text, num, roman->cur_sh->fwidth[col], align, 0, out, roman->cur_sh->row_format[row]); + pad_and_align(text, num, out_widths[col-c0], align, 0, out, roman->cur_sh->row_format[row]); fwprintf(fout, L"%ls", out); } } else if (emptyfield){ @@ -276,7 +335,7 @@ int save_plain(FILE * fout, int r0, int c0, int rn, int cn) { fwprintf(fout, L"%s\t", text); } } else if (! conf_clipboard_delimited_tab) { - fwprintf(fout, L"%*s", roman->cur_sh->fwidth[col], " "); + fwprintf(fout, L"%*s", out_widths[col-c0], " "); } else { fwprintf(fout, L"\t"); } diff --git a/src/conf.c b/src/conf.c index 6a0ea39..8d2cf95 100644 --- a/src/conf.c +++ b/src/conf.c @@ -93,6 +93,7 @@ const char default_config[] = #endif "copy_to_clipboard_delimited_tab=0\n" + "copy_to_clipboard_wysiwyg=1\n" #ifdef DEFAULT_PASTE_FROM_CLIPBOARD_CMD "default_paste_from_clipboard_cmd=" DEFAULT_PASTE_FROM_CLIPBOARD_CMD "\n" diff --git a/src/doc b/src/doc index 04f5c3a..e643b01 100755 --- a/src/doc +++ b/src/doc @@ -512,6 +512,9 @@ Commands for handling cell content: If you wish to delimit columns with tabs, to paste content directly to other spreadsheet programs, rather than an editor, set "copy_to_clipboard_delimited_tab" variable to "1". + If you wish to copy a full string representation of the range + instead of how its currently displayed in Sc-im, set + "copy_to_clipboard_wysiwyg" to "0". :cpaste Paste clipboard content to Sc-im. When 'cpaste' command is executed, the default value of macro @@ -2206,6 +2209,9 @@ Commands for handling cell content: COPY_TO_CLIPBOARD_DELIMITED_TAB COPY_TO_CLIPBOARD_DELIMITED_TAB = {NUMBER} NOCOPY_TO_CLIPBOARD_DELIMITED_TAB + COPY_TO_CLIPBOARD_WYSIWYG + COPY_TO_CLIPBOARD_WYSIWYG = {NUMBER} + NOCOPY_TO_CLIPBOARD_WYSIWYG DEFAULT_OPEN_FILE_UNDER_CURSOR_CMD = {strarg} NEWLINE_ACTION = {NUMBER} TM_GMTOFF diff --git a/src/gram.y b/src/gram.y index a79e495..9c243d7 100755 --- a/src/gram.y +++ b/src/gram.y @@ -289,6 +289,8 @@ token S_YANKCOL %token K_DEFAULT_PASTE_FROM_CLIPBOARD_CMD %token K_COPY_TO_CLIPBOARD_DELIMITED_TAB %token K_NOCOPY_TO_CLIPBOARD_DELIMITED_TAB +%token K_COPY_TO_CLIPBOARD_WYSIWYG +%token K_NOCOPY_TO_CLIPBOARD_WYSIWYG %token K_DEFAULT_OPEN_FILE_UNDER_CURSOR_CMD %token K_IMPORT_DELIMITED_TO_TEXT %token K_IGNORECASE @@ -1702,7 +1704,11 @@ setitem : { if ($3 == 0) parse_str(user_conf_d, "copy_to_clipboard_delimited_tab=0", TRUE); else parse_str(user_conf_d, "copy_to_clipboard_delimited_tab=1", TRUE); } | K_NOCOPY_TO_CLIPBOARD_DELIMITED_TAB { parse_str(user_conf_d, "copy_to_clipboard_delimited_tab=0", TRUE); } - + | K_COPY_TO_CLIPBOARD_WYSIWYG { parse_str(user_conf_d, "copy_to_clipboard_wysiwyg=1", TRUE); } + | K_COPY_TO_CLIPBOARD_WYSIWYG '=' NUMBER + { if ($3 == 0) parse_str(user_conf_d, "copy_to_clipboard_wysiwyg=0", TRUE); + else parse_str(user_conf_d, "copy_to_clipboard_wysiwyg=1", TRUE); } + | K_NOCOPY_TO_CLIPBOARD_WYSIWYG { parse_str(user_conf_d, "copy_to_clipboard_wysiwyg=0", TRUE); } | K_DEFAULT_OPEN_FILE_UNDER_CURSOR_CMD '=' strarg { char cmd[MAXCMD]; char * s = (char *) $3; -- cgit v1.2.3 From c61aca86a8199aa3cc676207904eec194f37495e Mon Sep 17 00:00:00 2001 From: Nicholas Todoroff Date: Thu, 17 Aug 2023 18:09:22 -0600 Subject: Fix pad_and_align() Properly null terminate str_out after wmemset(). Also remove unecessary calls to wcslen(). --- src/cmds/cmds.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/cmds/cmds.c b/src/cmds/cmds.c index ba2fba8..bc41389 100644 --- a/src/cmds/cmds.c +++ b/src/cmds/cmds.c @@ -2729,18 +2729,21 @@ void pad_and_align (char * str_value, char * numeric_value, int col_width, int a str_len = wcswidth(wcs_value, wcslen(wcs_value)); if (str_len == 2 && str_in[0] == '\\') { - wmemset(str_out + wcslen(str_out), str_in[1], col_width); + wmemset(str_out, str_in[1], col_width); + str_out[col_width] = L'\0'; free(str_in); return; } else if (str_len == 3 && str_in[0] == '\\' && str_in[1] == '\\') { - wmemset(str_out + wcslen(str_out), str_in[2], col_width); + wmemset(str_out, str_in[2], col_width); + str_out[col_width] = L'\0'; free(str_in); return; } // If padding exceedes column width, returns n number of '-' needed to fill column width if (padding >= col_width ) { - wmemset(str_out + wcslen(str_out), L' ', col_width); + wmemset(str_out, L' ', col_width); + str_out[col_width] = L'\0'; free(str_in); return; } @@ -2748,8 +2751,9 @@ void pad_and_align (char * str_value, char * numeric_value, int col_width, int a // If content exceedes column width, outputs n number of '*' needed to fill column width if (str_len + num_len + padding > col_width * rowfmt && ! get_conf_int("truncate") && ! get_conf_int("overlap") && ! get_conf_int("autowrap")) { - if (padding) wmemset(str_out + wcslen(str_out), L' ', padding); - wmemset(str_out + wcslen(str_out), L'*', col_width - padding); + if (padding) wmemset(str_out, L' ', padding); + wmemset(str_out + padding, L'*', col_width - padding); + str_out[col_width] = L'\0'; free(str_in); return; } -- cgit v1.2.3 From 09e65484181ea45dabf88fdad50cab9a5be5331d Mon Sep 17 00:00:00 2001 From: Nicholas Todoroff Date: Thu, 17 Aug 2023 18:23:49 -0600 Subject: Fix some grammar in src/doc --- src/doc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc b/src/doc index e643b01..cd9228b 100755 --- a/src/doc +++ b/src/doc @@ -509,9 +509,9 @@ Commands for handling cell content: runtime, using the :set command. This process will export content as plain text. It will not delimit columns with '\t' chars. - If you wish to delimit columns with tabs, to paste content - directly to other spreadsheet programs, rather than an - editor, set "copy_to_clipboard_delimited_tab" variable to "1". + If you wish to delimit columns with tabs in order to paste + content directly into other spreadsheet programs rather than + an editor, set "copy_to_clipboard_delimited_tab" to "1". If you wish to copy a full string representation of the range instead of how its currently displayed in Sc-im, set "copy_to_clipboard_wysiwyg" to "0". -- cgit v1.2.3 From 41270c42aca84fef96fd4b8dadf96fb67e4201ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s?= Date: Mon, 21 Aug 2023 13:38:27 -0300 Subject: fix typo --- src/clipboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clipboard.c b/src/clipboard.c index e08c74d..35d5159 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -227,7 +227,7 @@ int save_plain(FILE * fout, int r0, int c0, int rn, int cn) { // then that is the width used. // If it doesn't // then we use the largest data width found in the column and add 1. - if (!conf_clipboard_delimted_tab) { + if (!conf_clipboard_delimited_tab) { for (col = c0; col <= cn; ++col) { out_widths[col-c0] = roman->cur_sh->fwidth[col]; if (!conf_clipboard_wysiwyg) { -- cgit v1.2.3