| 2798 | |
| 2799 | |
| 2800 | #define MAXGOTOSHOW 4 |
| 2801 | #define MAXGOTOTYPED 12 |
| 2802 | |
| 2803 | |
| 2804 | void |
| 2805 | gtl_mem_fail (const char *msg) |
| 2806 | { |
| 2807 | message (D_ERROR, _(" Internal error: "), |
| 2808 | _("\n\n \"%s\"\n\n"), msg); |
| 2809 | } |
| 2810 | |
| 2811 | |
| 2812 | char * |
| 2813 | gtl_lines_saved_as_str (WEdit * edit, const long *nbrs_stored, int n_last) |
| 2814 | { |
| 2815 | static int once_showed = 0; |
| 2816 | int n, m; |
| 2817 | char *hist_clear_msg = NULL; |
| 2818 | char *str_line_N = NULL; |
| 2819 | char *str_stored_nbrs = NULL; |
| 2820 | |
| 2821 | if (n_last > MAXGOTOSHOW) |
| 2822 | n_last = MAXGOTOSHOW; |
| 2823 | |
| 2824 | if (once_showed == 0) { |
| 2825 | hist_clear_msg = |
| 2826 | g_strdup (_(" To clear `file-history' type key-char\n `c' or `C' then <Enter>\n\n ")); |
| 2827 | once_showed = 1; |
| 2828 | } else { |
| 2829 | hist_clear_msg = g_strdup (_(" ")); |
| 2830 | } |
| 2831 | |
| 2832 | if (edit_get_byte (edit, edit->last_byte - 1) == '\n') |
| 2833 | str_stored_nbrs = |
| 2834 | g_strdup_printf ("'\n%s %10li <= 0 bottom ('\\n' is next)\n %10li <= 1 upper line\n", |
| 2835 | hist_clear_msg, edit->total_lines, nbrs_stored[1]); |
| 2836 | else |
| 2837 | str_stored_nbrs = |
| 2838 | g_strdup_printf |
| 2839 | ("'\n%s %10li <= 0 bottom (next is not '\\n')\n %10li <= 1 upper line\n", |
| 2840 | hist_clear_msg, (edit->total_lines + 1), nbrs_stored[1]); |
| 2841 | |
| 2842 | g_free (hist_clear_msg); |
| 2843 | if (str_stored_nbrs == NULL) { |
| 2844 | gtl_mem_fail (_(" if ( str_stored_nbrs == NULL ) ")); |
| 2845 | return NULL; |
| 2846 | } |
| 2847 | |
| 2848 | if (n_last > 1) { |
| 2849 | m = 2; |
| 2850 | for (n = 2; n <= n_last; n++) { |
| 2851 | if (nbrs_stored[n] != 0) { |
| 2852 | str_line_N = g_strdup_printf (" %10li %2i\n", nbrs_stored[n], m++); |
| 2853 | if (str_line_N == NULL) { |
| 2854 | g_free (str_stored_nbrs); |
| 2855 | gtl_mem_fail (_(" if ( str_line_N == NULL ) ")); |
| 2856 | return NULL; |
| 2857 | } else { |
| 2858 | str_stored_nbrs = g_strconcat (str_stored_nbrs, str_line_N, (char *) NULL); |
| 2859 | g_free (str_line_N); |
| 2860 | if (str_stored_nbrs == NULL) { |
| 2861 | gtl_mem_fail (_(" if ( str_stored_nbrs == NULL ) ")); |
| 2862 | return NULL; |
| 2863 | } |
| 2864 | } |
| 2865 | } |
| 2866 | } |
| 2867 | |
| 2868 | if (str_stored_nbrs == NULL) |
| 2869 | gtl_mem_fail (_(" if ( str_stored_nbrs == NULL ) ")); |
| 2870 | } |
| 2871 | return str_stored_nbrs; |
| 2872 | } |
| 2873 | |
| 2874 | |
| 2875 | void |
| 2876 | gtl_gothis_nbr (WEdit * edit, long realgo_nbr) |
| 2877 | { |
| 2878 | /* when last line is new line (`\n') go to previous line */ |
| 2879 | if (realgo_nbr == 0) { |
| 2880 | return; |
| 2881 | } else if (realgo_nbr < 0) { |
| 2882 | if (edit_get_byte (edit, edit->last_byte - 1) != '\n') |
| 2883 | realgo_nbr++; |
| 2884 | |
| 2885 | realgo_nbr = edit->total_lines + realgo_nbr + 1; |
| 2886 | } |
| 2887 | edit_move_display (edit, realgo_nbr - (edit->num_widget_lines / 3)); |
| 2888 | edit_move_to_line (edit, realgo_nbr - 1); |
| 2889 | edit->force |= REDRAW_COMPLETELY; |
| 2890 | } |
| 2891 | |
| 2892 | |
| 2893 | long |
| 2894 | gtl_proceed_line_nbr (WEdit * edit, long *nbrs_stored, int *n_last, const long line_n) |
| 2895 | { |
| 2896 | int n, n0, ln, k, lk, realgo_nbr; |
| 2897 | |
| 2898 | if (line_n == 0 || line_n == -1) |
| 2899 | return (-1); |
| 2900 | |
| 2901 | if (line_n == 1) |
| 2902 | return line_n; |
| 2903 | |
| 2904 | if (line_n == nbrs_stored[*n_last]) |
| 2905 | return line_n; |
| 2906 | |
| 2907 | realgo_nbr = line_n; |
| 2908 | if (line_n > 0) { |
| 2909 | if (line_n <= *n_last) { |
| 2910 | realgo_nbr = nbrs_stored[line_n]; |
| 2911 | } else if (line_n >= edit->total_lines) { |
| 2912 | return (-1); |
| 2913 | } |
| 2914 | } else if (line_n <= -edit->total_lines) { |
| 2915 | return 1; |
| 2916 | } |
| 2917 | |
| 2918 | if (realgo_nbr == nbrs_stored[*n_last]) |
| 2919 | return realgo_nbr; |
| 2920 | |
| 2921 | for (n = 2; n < MAXGOTOSHOW; n++) { |
| 2922 | ln = nbrs_stored[n]; |
| 2923 | if (ln == edit->total_lines || ln == -edit->total_lines || ln == (edit->total_lines + 1) |
| 2924 | || ln == -(edit->total_lines + 1) |
| 2925 | || ln == 1 || ln == -1 || ln == realgo_nbr) |
| 2926 | nbrs_stored[n] = 0; |
| 2927 | } |
| 2928 | |
| 2929 | /* get rid of duplicates then store */ |
| 2930 | n0 = 0; |
| 2931 | for (n = MAXGOTOSHOW; n > 2; n--) { |
| 2932 | ln = nbrs_stored[n]; |
| 2933 | if (ln == 0) { |
| 2934 | n0 = 1; |
| 2935 | } else { |
| 2936 | for (k = 2; k < n; k++) { |
| 2937 | lk = nbrs_stored[k]; |
| 2938 | if (lk == 0) { |
| 2939 | n0 = 1; |
| 2940 | } else if (lk == ln) { |
| 2941 | nbrs_stored[k] = 0; |
| 2942 | n0 = 1; |
| 2943 | } |
| 2944 | } |
| 2945 | } |
| 2946 | } |
| 2947 | |
| 2948 | if (n0 != 0) { |
| 2949 | *n_last = 1; |
| 2950 | for (n = 2; n <= MAXGOTOSHOW; n++) { |
| 2951 | if (nbrs_stored[n] != 0) { |
| 2952 | nbrs_stored[++(*n_last)] = nbrs_stored[n]; |
| 2953 | if (*n_last < n) |
| 2954 | nbrs_stored[n] = 0; |
| 2955 | |
| 2956 | if (n == MAXGOTOSHOW) |
| 2957 | nbrs_stored[MAXGOTOSHOW] = 0; |
| 2958 | } |
| 2959 | } |
| 2960 | } |
| 2961 | |
| 2962 | if (*n_last >= MAXGOTOSHOW) { |
| 2963 | for (n = 2; n < MAXGOTOSHOW; n++) |
| 2964 | nbrs_stored[n] = nbrs_stored[n + 1]; |
| 2965 | |
| 2966 | *n_last = MAXGOTOSHOW - 1; |
| 2967 | } |
| 2968 | |
| 2969 | nbrs_stored[++(*n_last)] = realgo_nbr; |
| 2970 | return realgo_nbr; |
| 2971 | } |
| 2972 | |
| 2973 | |
| 2974 | void |
| 2975 | edit_goto_cmd (WEdit * edit) |
| 2976 | { |
| 2977 | const long long gtl_LONG_MAX = (long long) LONG_MAX; |
| 2978 | char *gtprompt = NULL; |
| 2979 | char str_displayed_nbr[MAXGOTOTYPED] = { '\0' }; |
| 2980 | char *str_input_type_error = NULL; |
| 2981 | char *usertyped_str = NULL; |
| 2982 | int errno_prev = 0; |
| 2983 | static int n_last = 2; |
| 2984 | static long realgo_nbr = 0; |
| 2985 | static long nbrs_stored[MAXGOTOSHOW + 1] = { -1, 1, MAXGOTOSHOW }; |
| 2986 | static long long typed_nbr = 0; |
| 2987 | |
| 2988 | if (edit->total_lines > gtl_LONG_MAX) |
| 2989 | return; |
| 2990 | |
| 2991 | if (edit->total_lines <= MAXGOTOSHOW) |
| 2992 | return; |
| 2993 | |
| 2994 | while (1) { |
| 2995 | str_displayed_nbr[0] = '\0'; |
| 2996 | g_snprintf (str_displayed_nbr, sizeof (str_displayed_nbr), "%li", nbrs_stored[n_last - 1]); |
| 2997 | gtl_proceed_line_nbr (edit, nbrs_stored, &n_last, edit->curs_line + 1); |
| 2998 | gtprompt = gtl_lines_saved_as_str (edit, nbrs_stored, n_last); |
| 2999 | usertyped_str = input_dialog (_(" Type right clmn or new line "), |
| 3000 | gtprompt, MC_HISTORY_EDIT_GOTO_LINE, str_displayed_nbr); |
| 3001 | g_free (gtprompt); |
| 3002 | if (usertyped_str == NULL) |
| 3003 | return; |
| 3004 | |
| 3005 | if (*usertyped_str == '\0') { |
| 3006 | /* |
| 3007 | message (2, _(" Empty string "), _( |
| 3008 | "\n typed:\n\n `%s' \n\n"), |
| 3009 | usertyped_str); |
| 3010 | */ |
| 3011 | g_free (usertyped_str); |
| 3012 | return; |
| 3013 | } |
| 3014 | if (('c' == usertyped_str[0] |
| 3015 | || 'C' == usertyped_str[0]) |
| 3016 | && '\0' == usertyped_str[1]) { |
| 3017 | g_free (usertyped_str); |
| 3018 | for (n_last = MAXGOTOSHOW; n_last > 1;) |
| 3019 | nbrs_stored[n_last--] = 0; |
| 3020 | |
| 3021 | } else if (strlen (usertyped_str) > MAXGOTOTYPED) { |
| 3022 | message (2, _(" too long typed string "), |
| 3023 | _("\n\n MAX strlen can be: `%i' " |
| 3024 | "\n\n MAX abs line number: `%li' \n\n"), |
| 3025 | MAXGOTOTYPED, labs (LONG_MAX)); |
| 3026 | g_free (usertyped_str); |
| 3027 | return; |
| 3028 | } else { |
| 3029 | errno_prev = errno; |
| 3030 | errno = 0; /* To distinguish success/failure after call */ |
| 3031 | |
| 3032 | typed_nbr = strtoll (usertyped_str, &str_input_type_error, 10); |
| 3033 | /* Check for various possible errors */ |
| 3034 | if (usertyped_str == str_input_type_error) { |
| 3035 | message (2, _(" No digits were found "), _("\n seems typed:\n\n `%s' " |
| 3036 | "\n\n has no digits\n\n"), usertyped_str); |
| 3037 | g_free (usertyped_str); |
| 3038 | return; |
| 3039 | } |
| 3040 | |
| 3041 | if (*str_input_type_error != '\0') { |
| 3042 | gtl_mem_fail (_(" if ( *str_input_type_error != '\0' ) ")); |
| 3043 | g_free (usertyped_str); |
| 3044 | return; |
| 3045 | } |
| 3046 | |
| 3047 | if (llabs (typed_nbr) > gtl_LONG_MAX) { |
| 3048 | message (2, _(" too big number "), |
| 3049 | _("\n\n MAX abs line number can be: `%lli'" |
| 3050 | "\n\n seems typed string is: `%s'" |
| 3051 | "\n\n and abs number is: `%lli'\n\n"), |
| 3052 | gtl_LONG_MAX, usertyped_str, llabs (typed_nbr)); |
| 3053 | g_free (usertyped_str); |
| 3054 | return; |
| 3055 | } |
| 3056 | errno = errno_prev; |
| 3057 | g_free (usertyped_str); |
| 3058 | realgo_nbr = gtl_proceed_line_nbr (edit, nbrs_stored, &n_last, (long) typed_nbr); |
| 3059 | break; |
| 3060 | } |
| 3061 | } |
| 3062 | gtl_gothis_nbr (edit, realgo_nbr); |
| 3063 | } |