| 2838 | |
| 2839 | |
| 2840 | #define MAXGOTOSHOW 3 |
| 2841 | #define MAXGOTOTYPED 12 |
| 2842 | |
| 2843 | void gtl_mem_fail (const char *msg, const char *funcname, const char *filename, const long line_n); |
| 2844 | char *gtl_lines_saved_as_str (WEdit * edit, const long *nbrs_stored, int n_last); |
| 2845 | void gtl_gothis_nbr (WEdit * edit, long realgo_nbr); |
| 2846 | long gtl_proceed_line_nbr (WEdit * edit, long *nbrs_stored, int *n_last, const long line_n); |
| 2847 | |
| 2848 | |
| 2849 | void |
| 2850 | gtl_mem_fail (const char *msg, const char *funcname, const char *filename, const long line_n) |
| 2851 | { |
| 2852 | message (D_ERROR, _(" Internal error: "), |
| 2853 | _("\n\n %s:%li:\n\n in FUNCTION\n\n %s\n\n \"%s\"\n\n"), |
| 2854 | filename, line_n, funcname, msg); |
| 2855 | } |
| 2856 | |
| 2857 | |
| 2858 | char * |
| 2859 | gtl_lines_saved_as_str (WEdit * edit, const long *nbrs_stored, int n_last) |
| 2860 | { |
| 2861 | static int once_showed = 0; |
| 2862 | int n, m; |
| 2863 | char *hist_clear_msg = NULL; |
| 2864 | char *str_line_N = NULL; |
| 2865 | char *str_stored_nbrs = NULL; |
| 2866 | |
| 2867 | if (n_last > MAXGOTOSHOW) |
| 2868 | n_last = MAXGOTOSHOW; |
| 2869 | |
| 2870 | if (once_showed == 0) { |
| 2871 | hist_clear_msg = |
| 2872 | g_strdup (_ |
| 2873 | (" To clear `file-history' type key-char\n `c' or `C' then <Enter>\n\n ")); |
| 2874 | once_showed = 1; |
| 2875 | } else { |
| 2876 | hist_clear_msg = g_strdup (_(" ")); |
| 2877 | } |
| 2878 | |
| 2879 | if (edit_get_byte (edit, edit->last_byte - 1) == '\n') |
| 2880 | str_stored_nbrs = |
| 2881 | g_strdup_printf ("'\n%s %10li <= 0 bottom ('\\n' is next)\n %10li <= 1 upper line\n", |
| 2882 | hist_clear_msg, edit->total_lines, nbrs_stored[1]); |
| 2883 | else |
| 2884 | str_stored_nbrs = |
| 2885 | g_strdup_printf |
| 2886 | ("'\n%s %10li <= 0 bottom (next is not '\\n')\n %10li <= 1 upper line\n", |
| 2887 | hist_clear_msg, (edit->total_lines + 1), nbrs_stored[1]); |
| 2888 | |
| 2889 | g_free (hist_clear_msg); |
| 2890 | if (str_stored_nbrs == NULL) { |
| 2891 | gtl_mem_fail (_(" if ( str_stored_nbrs == NULL ) "), __FUNCTION__, __FILE__, __LINE__); |
| 2892 | return NULL; |
| 2893 | } |
| 2894 | |
| 2895 | if (n_last > 1) { |
| 2896 | m = 2; |
| 2897 | for (n = 2; n <= n_last; n++) { |
| 2898 | if (nbrs_stored[n] != 0) { |
| 2899 | str_line_N = g_strdup_printf (" %10li %2i\n", nbrs_stored[n], m++); |
| 2900 | if (str_line_N == NULL) { |
| 2901 | g_free (str_stored_nbrs); |
| 2902 | gtl_mem_fail (_(" if ( str_line_N == NULL ) "), __FUNCTION__, __FILE__, __LINE__); |
| 2903 | return NULL; |
| 2904 | } else { |
| 2905 | str_stored_nbrs = g_strconcat (str_stored_nbrs, str_line_N, (char *) NULL); |
| 2906 | g_free (str_line_N); |
| 2907 | if (str_stored_nbrs == NULL) { |
| 2908 | gtl_mem_fail (_(" if ( str_stored_nbrs == NULL ) "), __FUNCTION__, __FILE__, __LINE__); |
| 2909 | return NULL; |
| 2910 | } |
| 2911 | } |
| 2912 | } |
| 2913 | } |
| 2914 | |
| 2915 | if (str_stored_nbrs == NULL) |
| 2916 | gtl_mem_fail (_(" if ( str_stored_nbrs == NULL ) "), __FUNCTION__, __FILE__, __LINE__); |
| 2917 | } |
| 2918 | return str_stored_nbrs; |
| 2919 | } |
| 2920 | |
| 2921 | |
| 2922 | void |
| 2923 | gtl_gothis_nbr (WEdit * edit, long realgo_nbr) |
| 2924 | { |
| 2925 | /* when last line is new line (`\n') go to previous line */ |
| 2926 | if (realgo_nbr == 0) { |
| 2927 | return; |
| 2928 | } else if (realgo_nbr < 0) { |
| 2929 | if (edit_get_byte (edit, edit->last_byte - 1) != '\n') |
| 2930 | realgo_nbr++; |
| 2931 | |
| 2932 | realgo_nbr = edit->total_lines + realgo_nbr + 1; |
| 2933 | } |
| 2934 | edit_move_display (edit, realgo_nbr - (edit->num_widget_lines / 3)); |
| 2935 | edit_move_to_line (edit, realgo_nbr - 1); |
| 2936 | edit->force |= REDRAW_COMPLETELY; |
| 2937 | } |
| 2938 | |
| 2939 | |
| 2940 | long |
| 2941 | gtl_proceed_line_nbr (WEdit * edit, long *nbrs_stored, int *n_last, const long line_n) |
| 2942 | { |
| 2943 | int n, n0, ln, k, lk, realgo_nbr; |
| 2944 | |
| 2945 | if (line_n == 0 || line_n == -1) |
| 2946 | return (-1); |
| 2947 | |
| 2948 | if (line_n == 1) |
| 2949 | return line_n; |
| 2950 | |
| 2951 | if (line_n == nbrs_stored[*n_last]) |
| 2952 | return line_n; |
| 2953 | |
| 2954 | realgo_nbr = line_n; |
| 2955 | if (line_n > 0) { |
| 2956 | if (line_n <= *n_last) { |
| 2957 | realgo_nbr = nbrs_stored[line_n]; |
| 2958 | } else if (line_n >= edit->total_lines) { |
| 2959 | return (-1); |
| 2960 | } |
| 2961 | } else if (line_n <= -edit->total_lines) { |
| 2962 | return 1; |
| 2963 | } |
| 2964 | |
| 2965 | if (realgo_nbr == nbrs_stored[*n_last]) |
| 2966 | return realgo_nbr; |
| 2967 | |
| 2968 | for (n = 2; n < MAXGOTOSHOW; n++) { |
| 2969 | ln = nbrs_stored[n]; |
| 2970 | if (ln == edit->total_lines || ln == -edit->total_lines || ln == (edit->total_lines + 1) |
| 2971 | || ln == -(edit->total_lines + 1) |
| 2972 | || ln == 1 || ln == -1 || ln == realgo_nbr) |
| 2973 | nbrs_stored[n] = 0; |
| 2974 | } |
| 2975 | |
| 2976 | /* get rid of duplicates then store */ |
| 2977 | n0 = 0; |
| 2978 | for (n = MAXGOTOSHOW; n > 2; n--) { |
| 2979 | ln = nbrs_stored[n]; |
| 2980 | if (ln == 0) { |
| 2981 | n0 = 1; |
| 2982 | } else { |
| 2983 | for (k = 2; k < n; k++) { |
| 2984 | lk = nbrs_stored[k]; |
| 2985 | if (lk == 0) { |
| 2986 | n0 = 1; |
| 2987 | } else if (lk == ln) { |
| 2988 | nbrs_stored[k] = 0; |
| 2989 | n0 = 1; |
| 2990 | } |
| 2991 | } |
| 2992 | } |
| 2993 | } |
| 2994 | |
| 2995 | if (n0 != 0) { |
| 2996 | *n_last = 1; |
| 2997 | for (n = 2; n <= MAXGOTOSHOW; n++) { |
| 2998 | if (nbrs_stored[n] != 0) { |
| 2999 | nbrs_stored[++(*n_last)] = nbrs_stored[n]; |
| 3000 | if (*n_last < n) |
| 3001 | nbrs_stored[n] = 0; |
| 3002 | |
| 3003 | if (n == MAXGOTOSHOW) |
| 3004 | nbrs_stored[MAXGOTOSHOW] = 0; |
| 3005 | } |
| 3006 | } |
| 3007 | } |
| 3008 | |
| 3009 | if (*n_last >= MAXGOTOSHOW) { |
| 3010 | for (n = 2; n < MAXGOTOSHOW; n++) |
| 3011 | nbrs_stored[n] = nbrs_stored[n + 1]; |
| 3012 | |
| 3013 | *n_last = MAXGOTOSHOW - 1; |
| 3014 | } |
| 3015 | |
| 3016 | nbrs_stored[++(*n_last)] = realgo_nbr; |
| 3017 | return realgo_nbr; |
| 3018 | } |
| 3019 | |
| 3020 | |
| 3021 | void |
| 3022 | edit_goto_cmd (WEdit * edit) |
| 3023 | { |
| 3024 | const long long gtl_LONG_MAX = (long long) LONG_MAX; |
| 3025 | char *gtprompt = NULL; |
| 3026 | char str_displayed_nbr[MAXGOTOTYPED] = { '\0' }; |
| 3027 | char *str_input_type_error = NULL; |
| 3028 | char *usertyped_str = NULL; |
| 3029 | int errno_prev = 0; |
| 3030 | static int n_last = 2; |
| 3031 | static long realgo_nbr = 0; |
| 3032 | static long nbrs_stored[MAXGOTOSHOW + 1] = { -1, 1, MAXGOTOSHOW }; |
| 3033 | static long long typed_nbr = 0; |
| 3034 | |
| 3035 | if (edit->total_lines > gtl_LONG_MAX) |
| 3036 | return; |
| 3037 | |
| 3038 | if (edit->total_lines <= MAXGOTOSHOW) |
| 3039 | return; |
| 3040 | |
| 3041 | while (1) { |
| 3042 | str_displayed_nbr[0] = '\0'; |
| 3043 | g_snprintf (str_displayed_nbr, sizeof (str_displayed_nbr), "%li", nbrs_stored[n_last - 1]); |
| 3044 | gtl_proceed_line_nbr (edit, nbrs_stored, &n_last, edit->curs_line + 1); |
| 3045 | gtprompt = gtl_lines_saved_as_str (edit, nbrs_stored, n_last); |
| 3046 | usertyped_str = input_dialog (_(" Type right clmn or new line "), |
| 3047 | gtprompt, MC_HISTORY_EDIT_GOTO_LINE, str_displayed_nbr); |
| 3048 | g_free (gtprompt); |
| 3049 | if (usertyped_str == NULL) |
| 3050 | return; |
| 3051 | |
| 3052 | if (*usertyped_str == '\0') { |
| 3053 | /* |
| 3054 | message (2, _(" Empty string "), _("\n %s : %s : %d : " |
| 3055 | "\n typed:\n\n `%s' \n\n"), |
| 3056 | __FUNCTION__, __FILE__, __LINE__, usertyped_str); |
| 3057 | */ |
| 3058 | g_free (usertyped_str); |
| 3059 | return; |
| 3060 | } |
| 3061 | if (('c' == usertyped_str[0] |
| 3062 | || 'C' == usertyped_str[0]) |
| 3063 | && '\0' == usertyped_str[1]) { |
| 3064 | g_free (usertyped_str); |
| 3065 | for (n_last = MAXGOTOSHOW; n_last > 1;) |
| 3066 | nbrs_stored[n_last--] = 0; |
| 3067 | |
| 3068 | } else if (strlen (usertyped_str) > MAXGOTOTYPED) { |
| 3069 | message (2, _(" too long typed string "), |
| 3070 | _("\n %s : %s : %d : " |
| 3071 | "\n\n MAX strlen can be: `%i' " |
| 3072 | "\n\n MAX abs line number: `%li' \n\n"), |
| 3073 | __FUNCTION__, __FILE__, __LINE__, MAXGOTOTYPED, labs (LONG_MAX)); |
| 3074 | g_free (usertyped_str); |
| 3075 | return; |
| 3076 | } else { |
| 3077 | errno_prev = errno; |
| 3078 | errno = 0; /* To distinguish success/failure after call */ |
| 3079 | |
| 3080 | typed_nbr = strtoll (usertyped_str, &str_input_type_error, 10); |
| 3081 | /* Check for various possible errors */ |
| 3082 | if (usertyped_str == str_input_type_error) { |
| 3083 | message (2, _(" No digits were found "), |
| 3084 | _("\n %s : %s : %d : " |
| 3085 | "\n seems typed:\n\n `%s' " |
| 3086 | "\n\n has no digits\n\n"), |
| 3087 | __FUNCTION__, __FILE__, __LINE__, usertyped_str); |
| 3088 | g_free (usertyped_str); |
| 3089 | return; |
| 3090 | } |
| 3091 | |
| 3092 | if (*str_input_type_error != '\0') { |
| 3093 | gtl_mem_fail (_(" if ( *str_input_type_error != '\0' ) "), __FUNCTION__, __FILE__, __LINE__); |
| 3094 | g_free (usertyped_str); |
| 3095 | return; |
| 3096 | } |
| 3097 | |
| 3098 | if (llabs (typed_nbr) > gtl_LONG_MAX) { |
| 3099 | message (2, _(" too big number "), |
| 3100 | _("\n %s : %s : %d : " |
| 3101 | "\n\n MAX abs line number can be: `%lli'" |
| 3102 | "\n\n seems typed string is: `%s'" |
| 3103 | "\n\n and abs number is: `%lli'\n\n"), |
| 3104 | __FUNCTION__, __FILE__, __LINE__, |
| 3105 | gtl_LONG_MAX, usertyped_str, llabs (typed_nbr)); |
| 3106 | g_free (usertyped_str); |
| 3107 | return; |
| 3108 | } |
| 3109 | errno = errno_prev; |
| 3110 | g_free (usertyped_str); |
| 3111 | realgo_nbr = gtl_proceed_line_nbr (edit, nbrs_stored, &n_last, (long) typed_nbr); |
| 3112 | break; |
| 3113 | } |
| 3114 | } |
| 3115 | gtl_gothis_nbr (edit, realgo_nbr); |
| 3116 | } |