ru.po: Heavily updated translation
[midnight-commander.git] / gtkedit / wordproc.c
blobed438df3e304672bb75b9fab049cdcefe8837894
1 /* wordproc.c - word-processor mode for the editor: does dynamic
2 paragraph formatting.
3 Copyright (C) 1996 Paul Sheer
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307, USA.
21 #include <config.h>
22 #include "edit.h"
23 #if defined (HAVE_MAD) && ! defined (MIDNIGHT) && ! defined (GTK)
24 #include "mad.h"
25 #endif
27 #ifdef MIDNIGHT
28 #define tab_width option_tab_spacing
29 #endif
31 int line_is_blank (WEdit * edit, long line);
33 #define NO_FORMAT_CHARS_START "-+*\\,.;:&>"
35 static long line_start (WEdit * edit, long line)
37 static long p = -1, l = 0;
38 int c;
39 if (p == -1 || abs (l - line) > abs (edit->curs_line - line)) {
40 l = edit->curs_line;
41 p = edit->curs1;
43 if (line < l)
44 p = edit_move_backward (edit, p, l - line);
45 else if (line > l)
46 p = edit_move_forward (edit, p, line - l, 0);
47 l = line;
48 p = edit_bol (edit, p);
49 while (strchr ("\t ", c = edit_get_byte (edit, p)))
50 p++;
51 return p;
54 static int bad_line_start (WEdit * edit, long p)
56 int c;
57 c = edit_get_byte (edit, p);
58 if (c == '.') { /* `...' is acceptable */
59 if (edit_get_byte (edit, p + 1) == '.')
60 if (edit_get_byte (edit, p + 2) == '.')
61 return 0;
62 return 1;
64 if (c == '-') {
65 if (edit_get_byte (edit, p + 1) == '-')
66 if (edit_get_byte (edit, p + 2) == '-')
67 return 0; /* `---' is acceptable */
68 return 1;
70 if (strchr (NO_FORMAT_CHARS_START, c))
71 return 1;
72 return 0;
75 static long begin_paragraph (WEdit * edit, long p, int force)
77 int i;
78 for (i = edit->curs_line - 1; i > 0; i--) {
79 if (line_is_blank (edit, i)) {
80 i++;
81 break;
83 if (force) {
84 if (bad_line_start (edit, line_start (edit, i))) {
85 i++;
86 break;
90 return edit_move_backward (edit, edit_bol (edit, edit->curs1), edit->curs_line - i);
93 static long end_paragraph (WEdit * edit, long p, int force)
95 int i;
96 for (i = edit->curs_line + 1; i < edit->total_lines; i++) {
97 if (line_is_blank (edit, i)) {
98 i--;
99 break;
101 if (force)
102 if (bad_line_start (edit, line_start (edit, i))) {
103 i--;
104 break;
107 return edit_eol (edit, edit_move_forward (edit, edit_bol (edit, edit->curs1), i - edit->curs_line, 0));
110 static char *get_paragraph (WEdit * edit, long p, long q, int indent, int *size)
112 char *s, *t;
113 #if 0
114 t = malloc ((q - p) + 2 * (q - p) / option_word_wrap_line_length + 10);
115 #else
116 t = malloc (2 * (q - p) + 100);
117 #endif
118 if (!t)
119 return 0;
120 for (s = t; p < q; p++, s++) {
121 if (indent)
122 if (edit_get_byte (edit, p - 1) == '\n')
123 while (strchr ("\t ", edit_get_byte (edit, p)))
124 p++;
125 *s = edit_get_byte (edit, p);
127 *size = (unsigned long) s - (unsigned long) t;
128 t[*size] = '\n';
129 return t;
132 static void strip_newlines (char *t, int size)
134 char *p = t;
135 while (size--) {
136 *p = *p == '\n' ? ' ' : *p;
137 p++;
141 #ifndef MIDNIGHT
142 int edit_width_of_long_printable (int c);
143 #endif
145 This is a copy of the function
146 int calc_text_pos (WEdit * edit, long b, long *q, int l)
147 in propfont.c :(
148 It calculates the number of chars in a line specified to length l in pixels
150 extern int tab_width;
151 static inline int next_tab_pos (int x)
153 return x += tab_width - x % tab_width;
155 static int line_pixel_length (char *t, long b, int l)
157 int x = 0, c, xn = 0;
158 for (;;) {
159 c = t[b];
160 switch (c) {
161 case '\n':
162 return b;
163 case '\t':
164 xn = next_tab_pos (x);
165 break;
166 default:
167 #ifdef MIDNIGHT
168 xn = x + 1;
169 #else
170 xn = x + edit_width_of_long_printable (c);
171 #endif
172 break;
174 if (xn > l)
175 break;
176 x = xn;
177 b++;
179 return b;
182 /* find the start of a word */
183 static int next_word_start (char *t, int q, int size)
185 int i;
186 for (i = q;; i++) {
187 switch (t[i]) {
188 case '\n':
189 return -1;
190 case '\t':
191 case ' ':
192 for (;; i++) {
193 if (t[i] == '\n')
194 return -1;
195 if (t[i] != ' ' && t[i] != '\t')
196 return i;
198 break;
203 /* find the start of a word */
204 static int word_start (char *t, int q, int size)
206 int i = q;
207 if (t[q] == ' ' || t[q] == '\t')
208 return next_word_start (t, q, size);
209 for (;;) {
210 int c;
211 if (!i)
212 return -1;
213 c = t[i - 1];
214 if (c == '\n')
215 return -1;
216 if (c == ' ' || c == '\t')
217 return i;
218 i--;
222 /* replaces ' ' with '\n' to properly format a paragraph */
223 static void format_this (char *t, int size, int indent)
225 int q = 0, ww;
226 strip_newlines (t, size);
227 ww = option_word_wrap_line_length * FONT_MEAN_WIDTH - indent;
228 if (ww < FONT_MEAN_WIDTH * 2)
229 ww = FONT_MEAN_WIDTH * 2;
230 for (;;) {
231 int p;
232 q = line_pixel_length (t, q, ww);
233 if (q > size)
234 break;
235 if (t[q] == '\n')
236 break;
237 p = word_start (t, q, size);
238 if (p == -1)
239 q = next_word_start (t, q, size); /* Return the end of the word if the beginning
240 of the word is at the beginning of a line
241 (i.e. a very long word) */
242 else
243 q = p;
244 if (q == -1) /* end of paragraph */
245 break;
246 if (q)
247 t[q - 1] = '\n';
251 static void replace_at (WEdit * edit, long q, int c)
253 edit_cursor_move (edit, q - edit->curs1);
254 edit_delete (edit);
255 edit_insert_ahead (edit, c);
258 void edit_insert_indent (WEdit * edit, int indent);
260 /* replaces a block of text */
261 static void put_paragraph (WEdit * edit, char *t, long p, long q, int indent, int size)
263 long cursor;
264 int i, c = 0;
265 cursor = edit->curs1;
266 if (indent)
267 while (strchr ("\t ", edit_get_byte (edit, p)))
268 p++;
269 for (i = 0; i < size; i++, p++) {
270 if (i && indent) {
271 if (t[i - 1] == '\n' && c == '\n') {
272 while (strchr ("\t ", edit_get_byte (edit, p)))
273 p++;
274 } else if (t[i - 1] == '\n') {
275 long curs;
276 edit_cursor_move (edit, p - edit->curs1);
277 curs = edit->curs1;
278 edit_insert_indent (edit, indent);
279 if (cursor >= curs)
280 cursor += edit->curs1 - p;
281 p = edit->curs1;
282 } else if (c == '\n') {
283 edit_cursor_move (edit, p - edit->curs1);
284 while (strchr ("\t ", edit_get_byte (edit, p))) {
285 edit_delete (edit);
286 if (cursor > edit->curs1)
287 cursor--;
289 p = edit->curs1;
292 c = edit_get_byte (edit, p);
293 if (c != t[i])
294 replace_at (edit, p, t[i]);
296 edit_cursor_move (edit, cursor - edit->curs1); /* restore cursor position */
299 int edit_indent_width (WEdit * edit, long p);
301 static int test_indent (WEdit * edit, long p, long q)
303 int indent;
304 indent = edit_indent_width (edit, p++);
305 if (!indent)
306 return 0;
307 for (; p < q; p++)
308 if (edit_get_byte (edit, p - 1) == '\n')
309 if (indent != edit_indent_width (edit, p))
310 return 0;
311 return indent;
314 void format_paragraph (WEdit * edit, int force)
316 long p, q;
317 int size;
318 char *t;
319 int indent = 0;
320 if (option_word_wrap_line_length < 2)
321 return;
322 if (line_is_blank (edit, edit->curs_line))
323 return;
324 p = begin_paragraph (edit, edit->curs1, force);
325 q = end_paragraph (edit, edit->curs1, force);
326 indent = test_indent (edit, p, q);
327 t = get_paragraph (edit, p, q, indent, &size);
328 if (!t)
329 return;
330 if (!force) {
331 int i;
332 if (strchr (NO_FORMAT_CHARS_START, *t)) {
333 free (t);
334 return;
336 for (i = 0; i < size - 1; i++) {
337 if (t[i] == '\n') {
338 if (strchr (NO_FORMAT_CHARS_START "\t ", t[i + 1])) {
339 free (t);
340 return;
345 format_this (t, q - p, indent);
346 put_paragraph (edit, t, p, q, indent, size);
347 free (t);