diff options
-rw-r--r-- | src/nvim/normal.c | 33 | ||||
-rw-r--r-- | src/nvim/normal.h | 41 | ||||
-rw-r--r-- | src/nvim/ops.c | 144 | ||||
-rw-r--r-- | src/nvim/path.c | 6 | ||||
-rw-r--r-- | src/nvim/ui.c | 27 | ||||
-rw-r--r-- | src/nvim/version.c | 102 | ||||
-rw-r--r-- | test/functional/server/server_spec.lua | 9 | ||||
-rw-r--r-- | third-party/CMakeLists.txt | 2 |
8 files changed, 230 insertions, 134 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c index a2e473fcb8..d4bf1c2e90 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1601,7 +1601,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) if (VIsual_mode == Ctrl_V) { /* block mode */ colnr_T start, end; - oap->block_mode = true; + oap->motion_type = MBLOCK; getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol); @@ -1711,11 +1711,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) */ if (oap->motion_force == NUL || oap->motion_type == MLINE) oap->inclusive = true; - if (VIsual_mode == 'V') + if (VIsual_mode == 'V') { oap->motion_type = MLINE; - else { + } else if (VIsual_mode == 'v') { oap->motion_type = MCHAR; - if (VIsual_mode != Ctrl_V && *ml_get_pos(&(oap->end)) == NUL + if (*ml_get_pos(&(oap->end)) == NUL && (include_line_break || !virtual_op) ) { oap->inclusive = false; @@ -1780,7 +1780,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) * oap->empty is set when start and end are the same. The inclusive * flag affects this too, unless yanking and the end is on a NUL. */ - oap->empty = (oap->motion_type == MCHAR + oap->empty = (oap->motion_type != MLINE && (!oap->inclusive || (oap->op_type == OP_YANK && gchar_pos(&oap->end) == NUL)) @@ -1810,14 +1810,13 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) * first non-blank in the line, the operator becomes linewise * (strange, but that's the way vi does it). */ - if ( oap->motion_type == MCHAR - && oap->inclusive == false - && !(cap->retval & CA_NO_ADJ_OP_END) - && oap->end.col == 0 - && (!oap->is_VIsual || *p_sel == 'o') - && !oap->block_mode - && oap->line_count > 1) { - oap->end_adjusted = true; /* remember that we did this */ + if (oap->motion_type == MCHAR + && oap->inclusive == false + && !(cap->retval & CA_NO_ADJ_OP_END) + && oap->end.col == 0 + && (!oap->is_VIsual || *p_sel == 'o') + && oap->line_count > 1) { + oap->end_adjusted = true; // remember that we did this --oap->line_count; --oap->end.lnum; if (inindent(0)) @@ -2044,7 +2043,6 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) } else { curwin->w_cursor = old_cursor; } - oap->block_mode = false; clearop(oap); } curwin->w_p_lbr = lbr_saved; @@ -2115,12 +2113,13 @@ static void op_function(oparg_T *oap) /* Exclude the end position. */ decl(&curbuf->b_op_end); - if (oap->block_mode) + if (oap->motion_type == MBLOCK) { argv[0] = (char_u *)"block"; - else if (oap->motion_type == MLINE) + } else if (oap->motion_type == MLINE) { argv[0] = (char_u *)"line"; - else + } else { argv[0] = (char_u *)"char"; + } /* Reset virtual_op so that 'virtualedit' can be changed in the * function. */ diff --git a/src/nvim/normal.h b/src/nvim/normal.h index 01259de6cd..95619c7ef6 100644 --- a/src/nvim/normal.h +++ b/src/nvim/normal.h @@ -14,28 +14,27 @@ * Arguments for operators. */ typedef struct oparg_S { - int op_type; /* current pending operator type */ - int regname; /* register to use for the operator */ - int motion_type; /* type of the current cursor motion */ - int motion_force; /* force motion type: 'v', 'V' or CTRL-V */ - bool use_reg_one; /* true if delete uses reg 1 even when not - linewise */ - bool inclusive; /* true if char motion is inclusive (only - valid when motion_type is MCHAR */ - bool end_adjusted; /* backuped b_op_end one char (only used by - do_format()) */ - pos_T start; /* start of the operator */ - pos_T end; /* end of the operator */ - pos_T cursor_start; /* cursor position before motion for "gw" */ + int op_type; // current pending operator type + int regname; // register to use for the operator + int motion_type; // type of the current cursor motion + int motion_force; // force motion type: 'v', 'V' or CTRL-V + bool use_reg_one; // true if delete uses reg 1 even when not + // linewise + bool inclusive; // true if char motion is inclusive (only + // valid when motion_type is MCHAR) + bool end_adjusted; // backuped b_op_end one char (only used by + // do_format()) + pos_T start; // start of the operator + pos_T end; // end of the operator + pos_T cursor_start; // cursor position before motion for "gw" - long line_count; /* number of lines from op_start to op_end - (inclusive) */ - bool empty; /* op_start and op_end the same (only used by - op_change()) */ - bool is_VIsual; /* operator on Visual area */ - bool block_mode; /* current operator is Visual block mode */ - colnr_T start_vcol; /* start col for block mode operator */ - colnr_T end_vcol; /* end col for block mode operator */ + long line_count; // number of lines from op_start to op_end + // (inclusive) + bool empty; // op_start and op_end the same (only used by + // op_change()) + bool is_VIsual; // operator on Visual area + colnr_T start_vcol; // start col for block mode operator + colnr_T end_vcol; // end col for block mode operator long prev_opcount; // ca.opcount saved for K_EVENT long prev_count0; // ca.count0 saved for K_EVENT } oparg_T; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 52b4fed9d7..707d20157a 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -174,20 +174,20 @@ void op_shift(oparg_T *oap, int curs_top, int amount) (linenr_T)(oap->end.lnum + 1)) == FAIL) return; - if (oap->block_mode) + if (oap->motion_type == MBLOCK) { block_col = curwin->w_cursor.col; + } for (i = oap->line_count - 1; i >= 0; i--) { first_char = *get_cursor_line_ptr(); - if (first_char == NUL) /* empty line */ + if (first_char == NUL) { // empty line curwin->w_cursor.col = 0; - else if (oap->block_mode) + } else if (oap->motion_type == MBLOCK) { shift_block(oap, amount); - else - /* Move the line right if it doesn't start with '#', 'smartindent' - * isn't set or 'cindent' isn't set or '#' isn't in 'cino'. */ - if (first_char != '#' || !preprocs_left()) { - shift_line(oap->op_type == OP_LSHIFT, p_sr, amount, FALSE); + } else if (first_char != '#' || !preprocs_left()) { + // Move the line right if it doesn't start with '#', 'smartindent' + // isn't set or 'cindent' isn't set or '#' isn't in 'cino'. + shift_line(oap->op_type == OP_LSHIFT, p_sr, amount, false); } ++curwin->w_cursor.lnum; } @@ -196,7 +196,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount) /* The cursor line is not in a closed fold */ foldOpenCursor(); - if (oap->block_mode) { + if (oap->motion_type == MBLOCK) { curwin->w_cursor.lnum = oap->start.lnum; curwin->w_cursor.col = block_col; } else if (curs_top) { /* put cursor on first line, for ">>" */ @@ -1275,8 +1275,9 @@ cmdline_paste_reg ( || (i < reg->y_size - 1 && !(remcr && i == reg->y_size - 2 - && *reg->y_array[i + 1] == NUL))) + && *reg->y_array[i + 1] == NUL))) { cmdline_paste_str((char_u *)"\r", literally); + } /* Check for CTRL-C, in case someone tries to paste a few thousand * lines and gets bored. */ @@ -1321,12 +1322,11 @@ int op_delete(oparg_T *oap) * line and motion_type == MCHAR and the result is a blank line, make the * delete linewise. Don't do this for the change command or Visual mode. */ - if ( oap->motion_type == MCHAR - && !oap->is_VIsual - && !oap->block_mode - && oap->line_count > 1 - && oap->motion_force == NUL - && oap->op_type == OP_DELETE) { + if (oap->motion_type == MCHAR + && !oap->is_VIsual + && oap->line_count > 1 + && oap->motion_force == NUL + && oap->op_type == OP_DELETE) { ptr = ml_get(oap->end.lnum) + oap->end.col; if (*ptr != NUL) ptr += oap->inclusive; @@ -1339,20 +1339,20 @@ int op_delete(oparg_T *oap) * Check for trying to delete (e.g. "D") in an empty line. * Note: For the change operator it is ok. */ - if ( oap->motion_type == MCHAR - && oap->line_count == 1 - && oap->op_type == OP_DELETE - && *ml_get(oap->start.lnum) == NUL) { - /* - * It's an error to operate on an empty region, when 'E' included in - * 'cpoptions' (Vi compatible). - */ - if (virtual_op) - /* Virtual editing: Nothing gets deleted, but we set the '[ and '] - * marks as if it happened. */ + if (oap->motion_type != MLINE + && oap->line_count == 1 + && oap->op_type == OP_DELETE + && *ml_get(oap->start.lnum) == NUL) { + // It's an error to operate on an empty region, when 'E' included in + // 'cpoptions' (Vi compatible). + if (virtual_op) { + // Virtual editing: Nothing gets deleted, but we set the '[ and '] + // marks as if it happened. goto setmarks; - if (vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL) + } + if (vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL) { beep_flush(); + } return OK; } @@ -1403,10 +1403,11 @@ int op_delete(oparg_T *oap) /* * block mode delete */ - if (oap->block_mode) { + if (oap->motion_type == MBLOCK) { if (u_save((linenr_T)(oap->start.lnum - 1), - (linenr_T)(oap->end.lnum + 1)) == FAIL) + (linenr_T)(oap->end.lnum + 1)) == FAIL) { return FAIL; + } for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; ++lnum) { block_prep(oap, &bd, lnum, TRUE); @@ -1594,7 +1595,7 @@ int op_delete(oparg_T *oap) msgmore(curbuf->b_ml.ml_line_count - old_lcount); setmarks: - if (oap->block_mode) { + if (oap->motion_type == MBLOCK) { curbuf->b_op_end.lnum = oap->end.lnum; curbuf->b_op_end.col = oap->start.col; } else @@ -1655,7 +1656,7 @@ int op_replace(oparg_T *oap, int c) /* * block mode replace */ - if (oap->block_mode) { + if (oap->motion_type == MBLOCK) { bd.is_MAX = (curwin->w_curswant == MAXCOL); for (; curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum) { curwin->w_cursor.col = 0; /* make sure cursor position is valid */ @@ -1837,7 +1838,7 @@ void op_tilde(oparg_T *oap) return; pos = oap->start; - if (oap->block_mode) { /* Visual block mode */ + if (oap->motion_type == MBLOCK) { // Visual block mode for (; pos.lnum <= oap->end.lnum; ++pos.lnum) { int one_change; @@ -1999,11 +2000,11 @@ void op_insert(oparg_T *oap, long count1) curwin->w_cursor.lnum = oap->start.lnum; update_screen(INVERTED); - if (oap->block_mode) { - /* When 'virtualedit' is used, need to insert the extra spaces before - * doing block_prep(). When only "block" is used, virtual edit is - * already disabled, but still need it when calling - * coladvance_force(). */ + if (oap->motion_type == MBLOCK) { + // When 'virtualedit' is used, need to insert the extra spaces before + // doing block_prep(). When only "block" is used, virtual edit is + // already disabled, but still need it when calling + // coladvance_force(). if (curwin->w_cursor.coladd > 0) { int old_ve_flags = ve_flags; @@ -2025,7 +2026,7 @@ void op_insert(oparg_T *oap, long count1) } if (oap->op_type == OP_APPEND) { - if (oap->block_mode + if (oap->motion_type == MBLOCK && curwin->w_cursor.coladd == 0 ) { /* Move the cursor to the character right of the block. */ @@ -2061,7 +2062,7 @@ void op_insert(oparg_T *oap, long count1) if (curwin->w_cursor.lnum != oap->start.lnum || got_int) return; - if (oap->block_mode) { + if (oap->motion_type == MBLOCK) { struct block_def bd2; /* The user may have moved the cursor before inserting something, try @@ -2166,13 +2167,14 @@ int op_change(oparg_T *oap) && !virtual_op) inc_cursor(); - /* check for still on same line (<CR> in inserted text meaningless) */ - /* skip blank lines too */ - if (oap->block_mode) { - /* Add spaces before getting the current line length. */ + // check for still on same line (<CR> in inserted text meaningless) + // skip blank lines too + if (oap->motion_type == MBLOCK) { + // Add spaces before getting the current line length. if (virtual_op && (curwin->w_cursor.coladd > 0 - || gchar_cursor() == NUL)) + || gchar_cursor() == NUL)) { coladvance_force(getviscol()); + } firstline = ml_get(oap->start.lnum); pre_textlen = (long)STRLEN(firstline); pre_indent = (long)(skipwhite(firstline) - firstline); @@ -2189,9 +2191,10 @@ int op_change(oparg_T *oap) * block. * Don't repeat the insert when Insert mode ended with CTRL-C. */ - if (oap->block_mode && oap->start.lnum != oap->end.lnum && !got_int) { - /* Auto-indenting may have changed the indent. If the cursor was past - * the indent, exclude that indent change from the inserted text. */ + if (oap->motion_type == MBLOCK + && oap->start.lnum != oap->end.lnum && !got_int) { + // Auto-indenting may have changed the indent. If the cursor was past + // the indent, exclude that indent change from the inserted text. firstline = ml_get(oap->start.lnum); if (bd.textcol > (colnr_T)pre_indent) { long new_indent = (long)(skipwhite(firstline) - firstline); @@ -2332,13 +2335,12 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) * If the cursor was in column 1 before and after the movement, and the * operator is not inclusive, the yank is always linewise. */ - if ( oap->motion_type == MCHAR - && oap->start.col == 0 - && !oap->inclusive - && (!oap->is_VIsual || *p_sel == 'o') - && !oap->block_mode - && oap->end.col == 0 - && yanklines > 1) { + if (oap->motion_type == MCHAR + && oap->start.col == 0 + && !oap->inclusive + && (!oap->is_VIsual || *p_sel == 'o') + && oap->end.col == 0 + && yanklines > 1) { yanktype = MLINE; --yankendlnum; --yanklines; @@ -2354,9 +2356,8 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) y_idx = 0; lnum = oap->start.lnum; - if (oap->block_mode) { - /* Visual block mode */ - reg->y_type = MBLOCK; /* set the yank register type */ + if (yanktype == MBLOCK) { + // Visual block mode reg->y_width = oap->end_vcol - oap->start_vcol; if (curwin->w_curswant == MAXCOL && reg->y_width > 0) @@ -2470,25 +2471,26 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) if (curwin->w_p_rnu) { redraw_later(SOME_VALID); // cursor moved to start } - if (message) { /* Display message about yank? */ - if (yanktype == MCHAR - && !oap->block_mode - && yanklines == 1) + if (message) { // Display message about yank? + if (yanktype == MCHAR && yanklines == 1) { yanklines = 0; - /* Some versions of Vi use ">=" here, some don't... */ + } + // Some versions of Vi use ">=" here, some don't... if (yanklines > p_report) { - /* redisplay now, so message is not deleted */ + // redisplay now, so message is not deleted update_topline_redraw(); if (yanklines == 1) { - if (oap->block_mode) + if (yanktype == MBLOCK) { MSG(_("block of 1 line yanked")); - else + } else { MSG(_("1 line yanked")); - } else if (oap->block_mode) + } + } else if (yanktype == MBLOCK) { smsg(_("block of %" PRId64 " lines yanked"), (int64_t)yanklines); - else + } else { smsg(_("%" PRId64 " lines yanked"), (int64_t)yanklines); + } } } @@ -2497,9 +2499,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) */ curbuf->b_op_start = oap->start; curbuf->b_op_end = oap->end; - if (yanktype == MLINE - && !oap->block_mode - ) { + if (yanktype == MLINE) { curbuf->b_op_start.col = 0; curbuf->b_op_end.col = MAXCOL; } @@ -4903,7 +4903,7 @@ void cursor_pos_info(void) /* Make 'sbr' empty for a moment to get the correct size. */ p_sbr = empty_option; oparg.is_VIsual = true; - oparg.block_mode = true; + oparg.motion_type = MBLOCK; oparg.op_type = OP_NOP; getvcols(curwin, &min_pos, &max_pos, &oparg.start_vcol, &oparg.end_vcol); diff --git a/src/nvim/path.c b/src/nvim/path.c index 253035ed99..d689eaf8cb 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -579,9 +579,13 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, s = p + 1; } else if (path_end >= path + wildoff && (vim_strchr((char_u *)"*?[{~$", *path_end) != NULL +#ifndef WIN32 || (!p_fic && (flags & EW_ICASE) - && isalpha(PTR2CHAR(path_end))))) + && isalpha(PTR2CHAR(path_end)))) +#endif + ) { e = p; + } if (has_mbyte) { len = (*mb_ptr2len)(path_end); STRNCPY(p, path_end, len); diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 786f6026de..d32969f149 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -55,14 +55,25 @@ static int height, width; // // See http://stackoverflow.com/a/11172679 for a better explanation of how it // works. -#define UI_CALL(...) \ - do { \ - flush_cursor_update(); \ - for (size_t i = 0; i < ui_count; i++) { \ - UI *ui = uis[i]; \ - UI_CALL_HELPER(CNT(__VA_ARGS__), __VA_ARGS__); \ - } \ - } while (0) +#ifdef _MSC_VER + #define UI_CALL(funname, ...) \ + do { \ + flush_cursor_update(); \ + for (size_t i = 0; i < ui_count; i++) { \ + UI *ui = uis[i]; \ + UI_CALL_MORE(funname, __VA_ARGS__); \ + } \ + } while (0) +#else + #define UI_CALL(...) \ + do { \ + flush_cursor_update(); \ + for (size_t i = 0; i < ui_count; i++) { \ + UI *ui = uis[i]; \ + UI_CALL_HELPER(CNT(__VA_ARGS__), __VA_ARGS__); \ + } \ + } while (0) +#endif #define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, ZERO, ignore) #define SELECT_NTH(a1, a2, a3, a4, a5, a6, ...) a6 #define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__) diff --git a/src/nvim/version.c b/src/nvim/version.c index b097ac4702..39d5b0f1b0 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -71,6 +71,84 @@ static char *features[] = { // clang-format off static int included_patches[] = { + // 1000, + // 999 NA + // 998, + // 997 NA + // 996 NA + // 995 NA + // 994 NA + // 993, + // 992 NA + // 991, + // 990 NA + // 989, + // 988 NA + // 987 NA + // 986 NA + // 985 NA + // 984, + // 983, + // 982, + // 981, + // 980, + // 979 NA + // 978, + // 977, + // 976 NA + // 975, + // 974, + // 973, + // 972, + // 971, + // 970, + // 969, + // 968, + // 967 NA + // 966 NA + // 965 NA + // 964, + // 963, + // 962 NA + // 961, + // 960 NA + // 959 NA + // 958, + // 957, + // 956, + // 955, + // 954 NA + // 953, + // 952, + // 951, + // 950, + // 949, + // 948 NA + // 947, + // 946, + // 945, + // 944, + // 943, + // 942, + // 941, + // 940 NA + // 939, + // 938 NA + // 937, + // 936, + // 935, + // 934 NA + // 933, + // 932, + // 931, + // 930 NA + // 929, + // 928 NA + // 927 NA + // 926, + // 925, + // 924 NA + // 923 NA // 922, // 921 NA // 920 NA @@ -129,8 +207,8 @@ static int included_patches[] = { // 867 NA // 866, // 865, - // 864, - // 863, + // 864 NA + // 863 NA // 862 NA // 861 NA // 860, @@ -139,7 +217,7 @@ static int included_patches[] = { // 857, // 856, // 855 NA - // 854, + // 854 NA // 853, // 852 NA // 851 NA @@ -151,8 +229,8 @@ static int included_patches[] = { // 845, // 844, // 843, - // 842, - // 841, + // 842 NA + // 841 NA // 840 NA // 839, // 838, @@ -185,7 +263,7 @@ static int included_patches[] = { // 811, // 810, 809, - // 808, + // 808 NA // 807, // 806, // 805, @@ -332,7 +410,7 @@ static int included_patches[] = { // 664 NA // 663 NA // 662, - // 661, + // 661 NA 660, 659, 658, @@ -352,7 +430,7 @@ static int included_patches[] = { // 644 NA // 643, // 642, - // 641, + // 641 NA 640, // 639, // 638 NA @@ -365,15 +443,15 @@ static int included_patches[] = { 631, 630, 629, - // 628, + // 628 NA // 627 NA // 626 NA // 625 NA - // 624, + // 624 NA 623, // 622 NA // 621 NA - // 620, + // 620 NA // 619 NA // 618 NA 617, @@ -386,7 +464,7 @@ static int included_patches[] = { // 610 NA 609, 608, - // 607, + // 607 NA 606, // 605, 604, diff --git a/test/functional/server/server_spec.lua b/test/functional/server/server_spec.lua index d9ce96057e..e8a5743446 100644 --- a/test/functional/server/server_spec.lua +++ b/test/functional/server/server_spec.lua @@ -38,8 +38,13 @@ describe('serverstart(), serverstop()', function() eq('', eval('v:servername')) -- v:servername will take the next available server. - nvim('command', "call serverstart('test_server_socket')") - eq('test_server_socket', eval('v:servername')) + if eval('has("win32")') then + nvim('command', "call serverstart('\\\\.\\pipe\\test_server_pipe')") + eq('\\\\.\\pipe\\test_server_pipe', eval('v:servername')) + else + nvim('command', "call serverstart('test_server_socket')") + eq('test_server_socket', eval('v:servername')) + end end) it('serverstop() ignores invalid input', function() diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 7f582d3199..de421365c4 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -77,7 +77,7 @@ set(LIBUV_SHA256 db5d46318e18330c696d954747036e1be8e2346411d4f30236d7e2f499f0cfa set(MSGPACK_URL https://github.com/msgpack/msgpack-c/archive/cpp-1.0.0.tar.gz) set(MSGPACK_SHA256 afda64ca445203bb7092372b822bae8b2539fdcebbfc3f753f393628c2bcfe7d) -set(LUAJIT_URL https://github.com/neovim/deps/raw/master/src/LuaJIT-2.0.4.tar.gz) +set(LUAJIT_URL https://github.com/neovim/deps/raw/master/opt/LuaJIT-2.0.4.tar.gz) set(LUAJIT_SHA256 620fa4eb12375021bef6e4f237cbd2dd5d49e56beb414bee052c746beef1807d) set(LUAROCKS_URL https://github.com/keplerproject/luarocks/archive/5d8a16526573b36d5b22aa74866120c998466697.tar.gz) |