change explorer quick launch icon to use default 'my computer' icon instead of a...
[reactos.git] / rosapps / mc / edit / wordproc.c
1 /* wordproc.c - word-processor mode for the editor: does dynamic
2 paragraph formatting.
3 Copyright (C) 1996 Paul Sheer
4
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.
9
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.
14
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <config.h>
21 #include "edit.h"
22
23 #ifdef MIDNIGHT
24 #define tab_width option_tab_spacing
25 #endif
26
27 int line_is_blank (WEdit * edit, long line);
28
29 #define NO_FORMAT_CHARS_START "-+*\\,.;:&>"
30
31 static long line_start (WEdit * edit, long line)
32 {
33 static long p = -1, l = 0;
34 int c;
35 if (p == -1 || abs (l - line) > abs (edit->curs_line - line)) {
36 l = edit->curs_line;
37 p = edit->curs1;
38 }
39 if (line < l)
40 p = edit_move_backward (edit, p, l - line);
41 else if (line > l)
42 p = edit_move_forward (edit, p, line - l, 0);
43 l = line;
44 p = edit_bol (edit, p);
45 while (strchr ("\t ", c = edit_get_byte (edit, p)))
46 p++;
47 return p;
48 }
49
50 static int bad_line_start (WEdit * edit, long p)
51 {
52 int c;
53 c = edit_get_byte (edit, p);
54 if (c == '.') { /* `...' is acceptable */
55 if (edit_get_byte (edit, p + 1) == '.')
56 if (edit_get_byte (edit, p + 2) == '.')
57 return 0;
58 return 1;
59 }
60 if (c == '-') {
61 if (edit_get_byte (edit, p + 1) == '-')
62 if (edit_get_byte (edit, p + 2) == '-')
63 return 0; /* `---' is acceptable */
64 return 1;
65 }
66 if (strchr (NO_FORMAT_CHARS_START, c))
67 return 1;
68 return 0;
69 }
70
71 static long begin_paragraph (WEdit * edit, long p, int force)
72 {
73 int i;
74 for (i = edit->curs_line - 1; i > 0; i--) {
75 if (line_is_blank (edit, i)) {
76 i++;
77 break;
78 }
79 if (force) {
80 if (bad_line_start (edit, line_start (edit, i))) {
81 i++;
82 break;
83 }
84 }
85 }
86 return edit_move_backward (edit, edit_bol (edit, edit->curs1), edit->curs_line - i);
87 }
88
89 static long end_paragraph (WEdit * edit, long p, int force)
90 {
91 int i;
92 for (i = edit->curs_line + 1; i < edit->total_lines; i++) {
93 if (line_is_blank (edit, i)) {
94 i--;
95 break;
96 }
97 if (force)
98 if (bad_line_start (edit, line_start (edit, i))) {
99 i--;
100 break;
101 }
102 }
103 return edit_eol (edit, edit_move_forward (edit, edit_bol (edit, edit->curs1), i - edit->curs_line, 0));
104 }
105
106 static char *get_paragraph (WEdit * edit, long p, long q, int indent, int *size)
107 {
108 char *s, *t;
109 t = malloc ((q - p) + 2 * (q - p) / option_word_wrap_line_length + 10);
110 if (!t)
111 return 0;
112 for (s = t; p < q; p++, s++) {
113 if (indent)
114 if (edit_get_byte (edit, p - 1) == '\n')
115 while (strchr ("\t ", edit_get_byte (edit, p)))
116 p++;
117 *s = edit_get_byte (edit, p);
118 }
119 *size = (unsigned long) s - (unsigned long) t;
120 t[*size] = '\n';
121 return t;
122 }
123
124 static void strip_newlines (char *t, int size)
125 {
126 char *p = t;
127 while (size--) {
128 *p = *p == '\n' ? ' ' : *p;
129 p++;
130 }
131 }
132
133 #ifndef MIDNIGHT
134 int edit_width_of_long_printable (int c);
135 #endif
136 /*
137 This is a copy of the function
138 int calc_text_pos (WEdit * edit, long b, long *q, int l)
139 in propfont.c :(
140 It calculates the number of chars in a line specified to length l in pixels
141 */
142 extern int tab_width;
143 static inline int next_tab_pos (int x)
144 {
145 return x += tab_width - x % tab_width;
146 }
147 static int line_pixel_length (char *t, long b, int l)
148 {
149 int x = 0, c, xn = 0;
150 for (;;) {
151 c = t[b];
152 switch (c) {
153 case '\n':
154 return b;
155 case '\t':
156 xn = next_tab_pos (x);
157 break;
158 default:
159 #ifdef MIDNIGHT
160 xn = x + 1;
161 #else
162 xn = x + edit_width_of_long_printable (c);
163 #endif
164 break;
165 }
166 if (xn > l)
167 break;
168 x = xn;
169 b++;
170 }
171 return b;
172 }
173
174 /* find the start of a word */
175 static int next_word_start (char *t, int q, int size)
176 {
177 int i;
178 for (i = q;; i++) {
179 switch (t[i]) {
180 case '\n':
181 return -1;
182 case '\t':
183 case ' ':
184 for (;; i++) {
185 if (t[i] == '\n')
186 return -1;
187 if (t[i] != ' ' && t[i] != '\t')
188 return i;
189 }
190 break;
191 }
192 }
193 }
194
195 /* find the start of a word */
196 static int word_start (char *t, int q, int size)
197 {
198 int i = q;
199 if (t[q] == ' ' || t[q] == '\t')
200 return next_word_start (t, q, size);
201 for (;;) {
202 int c;
203 if (!i)
204 return -1;
205 c = t[i - 1];
206 if (c == '\n')
207 return -1;
208 if (c == ' ' || c == '\t')
209 return i;
210 i--;
211 }
212 }
213
214 /* replaces ' ' with '\n' to properly format a paragraph */
215 static void format_this (char *t, int size, int indent)
216 {
217 int q = 0, ww;
218 strip_newlines (t, size);
219 ww = option_word_wrap_line_length * FONT_MEAN_WIDTH - indent;
220 if (ww < FONT_MEAN_WIDTH * 2)
221 ww = FONT_MEAN_WIDTH * 2;
222 for (;;) {
223 int p;
224 q = line_pixel_length (t, q, ww);
225 if (q > size)
226 break;
227 if (t[q] == '\n')
228 break;
229 p = word_start (t, q, size);
230 if (p == -1)
231 q = next_word_start (t, q, size); /* Return the end of the word if the beginning
232 of the word is at the beginning of a line
233 (i.e. a very long word) */
234 else
235 q = p;
236 if (q == -1) /* end of paragraph */
237 break;
238 if (q)
239 t[q - 1] = '\n';
240 }
241 }
242
243 static void replace_at (WEdit * edit, long q, int c)
244 {
245 edit_cursor_move (edit, q - edit->curs1);
246 edit_delete (edit);
247 edit_insert_ahead (edit, c);
248 }
249
250 void edit_insert_indent (WEdit * edit, int indent);
251
252 /* replaces a block of text */
253 static void put_paragraph (WEdit * edit, char *t, long p, long q, int indent, int size)
254 {
255 long cursor;
256 int i, c = 0;
257 cursor = edit->curs1;
258 if (indent)
259 while (strchr ("\t ", edit_get_byte (edit, p)))
260 p++;
261 for (i = 0; i < size; i++, p++) {
262 if (i && indent) {
263 if (t[i - 1] == '\n' && c == '\n') {
264 while (strchr ("\t ", edit_get_byte (edit, p)))
265 p++;
266 } else if (t[i - 1] == '\n') {
267 long curs;
268 edit_cursor_move (edit, p - edit->curs1);
269 curs = edit->curs1;
270 edit_insert_indent (edit, indent);
271 if (cursor >= curs)
272 cursor += edit->curs1 - p;
273 p = edit->curs1;
274 } else if (c == '\n') {
275 edit_cursor_move (edit, p - edit->curs1);
276 while (strchr ("\t ", edit_get_byte (edit, p))) {
277 edit_delete (edit);
278 if (cursor > edit->curs1)
279 cursor--;
280 }
281 p = edit->curs1;
282 }
283 }
284 c = edit_get_byte (edit, p);
285 if (c != t[i])
286 replace_at (edit, p, t[i]);
287 }
288 edit_cursor_move (edit, cursor - edit->curs1); /* restore cursor position */
289 }
290
291 int edit_indent_width (WEdit * edit, long p);
292
293 static int test_indent (WEdit * edit, long p, long q)
294 {
295 int indent;
296 indent = edit_indent_width (edit, p++);
297 if (!indent)
298 return 0;
299 for (; p < q; p++)
300 if (edit_get_byte (edit, p - 1) == '\n')
301 if (indent != edit_indent_width (edit, p))
302 return 0;
303 return indent;
304 }
305
306 void format_paragraph (WEdit * edit, int force)
307 {
308 long p, q;
309 int size;
310 char *t;
311 int indent = 0;
312 if (option_word_wrap_line_length < 2)
313 return;
314 if (line_is_blank (edit, edit->curs_line))
315 return;
316 p = begin_paragraph (edit, edit->curs1, force);
317 q = end_paragraph (edit, edit->curs1, force);
318 indent = test_indent (edit, p, q);
319 t = get_paragraph (edit, p, q, indent, &size);
320 if (!t)
321 return;
322 if (!force) {
323 int i;
324 if (strchr (NO_FORMAT_CHARS_START, *t)) {
325 free (t);
326 return;
327 }
328 for (i = 0; i < size - 1; i++) {
329 if (t[i] == '\n') {
330 if (strchr (NO_FORMAT_CHARS_START "\t ", t[i + 1])) {
331 free (t);
332 return;
333 }
334 }
335 }
336 }
337 format_this (t, q - p, indent);
338 put_paragraph (edit, t, p, q, indent, size);
339 free (t);
340 }
341
342
343
344
345
346
347
348
349
350