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