154
|
1 /* Calculate what line insertion or deletion to do, and do it,
|
75227
|
2 Copyright (C) 1985, 1986, 1990, 1993, 1994, 2001, 2002, 2003, 2004,
|
106815
|
3 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
154
|
4
|
|
5 This file is part of GNU Emacs.
|
|
6
|
94963
|
7 GNU Emacs is free software: you can redistribute it and/or modify
|
154
|
8 it under the terms of the GNU General Public License as published by
|
94963
|
9 the Free Software Foundation, either version 3 of the License, or
|
|
10 (at your option) any later version.
|
154
|
11
|
|
12 GNU Emacs is distributed in the hope that it will be useful,
|
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 GNU General Public License for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
94963
|
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
154
|
19
|
|
20
|
4696
|
21 #include <config.h>
|
25004
|
22 #include <stdio.h>
|
105669
|
23 #include <setjmp.h>
|
53229
33c3c7c16e13
lib-src/emacsclient.c: Implemented --here option (open a new Emacs tty). Needs more work.
Karoly Lorentey <lorentey@elte.hu>
diff
changeset
|
24 #include "lisp.h"
|
154
|
25 #include "termchar.h"
|
|
26 #include "dispextern.h"
|
31102
|
27 #include "keyboard.h"
|
766
|
28 #include "frame.h"
|
25004
|
29 #include "window.h"
|
82990
2ecd1f669db9
Fixed X support, preliminary support for X-tty combo sessions.
Karoly Lorentey <lorentey@elte.hu>
diff
changeset
|
30 #include "termhooks.h"
|
154
|
31
|
|
32 /* All costs measured in characters.
|
766
|
33 So no cost can exceed the area of a frame, measured in characters.
|
6773
|
34 Let's hope this is never more than 1000000 characters. */
|
154
|
35
|
6773
|
36 #define INFINITY 1000000
|
154
|
37
|
|
38 struct matrix_elt
|
|
39 {
|
|
40 /* Cost of outputting through this line
|
|
41 if no insert/delete is done just above it. */
|
6773
|
42 int writecost;
|
154
|
43 /* Cost of outputting through this line
|
|
44 if an insert is done just above it. */
|
6773
|
45 int insertcost;
|
154
|
46 /* Cost of outputting through this line
|
|
47 if a delete is done just above it. */
|
6773
|
48 int deletecost;
|
154
|
49 /* Number of inserts so far in this run of inserts,
|
|
50 for the cost in insertcost. */
|
6773
|
51 unsigned char insertcount;
|
154
|
52 /* Number of deletes so far in this run of deletes,
|
|
53 for the cost in deletecost. */
|
6773
|
54 unsigned char deletecount;
|
10262
|
55 /* Number of writes so far since the last insert
|
|
56 or delete for the cost in writecost. */
|
|
57 unsigned char writecount;
|
154
|
58 };
|
|
59
|
109100
|
60 static void do_direct_scrolling (struct frame *,
|
|
61 struct glyph_matrix *,
|
|
62 struct matrix_elt *,
|
|
63 int, int);
|
|
64 static void do_scrolling (struct frame *,
|
|
65 struct glyph_matrix *,
|
|
66 struct matrix_elt *,
|
|
67 int, int);
|
25004
|
68
|
154
|
69
|
10262
|
70 /* Determine, in matrix[i,j], the cost of updating the first j old
|
|
71 lines into the first i new lines using the general scrolling method.
|
154
|
72 This involves using insert or delete somewhere if i != j.
|
|
73 For each matrix elements, three kinds of costs are recorded:
|
|
74 the smallest cost that ends with an insert, the smallest
|
|
75 cost that ends with a delete, and the smallest cost that
|
|
76 ends with neither one. These are kept separate because
|
|
77 on some terminals the cost of doing an insert varies
|
|
78 depending on whether one was just done, etc. */
|
|
79
|
|
80 /* draw_cost[VPOS] is the cost of outputting new line at VPOS.
|
|
81 old_hash[VPOS] is the hash code of the old line at VPOS.
|
|
82 new_hash[VPOS] is the hash code of the new line at VPOS.
|
766
|
83 Note that these are not true frame vpos's, but relative
|
154
|
84 to the place at which the first mismatch between old and
|
|
85 new contents appears. */
|
|
86
|
|
87 static void
|
109139
|
88 calculate_scrolling (FRAME_PTR frame,
|
|
89 /* matrix is of size window_size + 1 on each side. */
|
|
90 struct matrix_elt *matrix,
|
|
91 int window_size, int lines_below,
|
|
92 int *draw_cost, int *old_hash, int *new_hash,
|
|
93 int free_at_end)
|
154
|
94 {
|
|
95 register int i, j;
|
110550
|
96 EMACS_INT frame_lines = FRAME_LINES (frame);
|
154
|
97 register struct matrix_elt *p, *p1;
|
|
98 register int cost, cost1;
|
|
99
|
53225
|
100 int lines_moved = window_size
|
82990
2ecd1f669db9
Fixed X support, preliminary support for X-tty combo sessions.
Karoly Lorentey <lorentey@elte.hu>
diff
changeset
|
101 + (FRAME_SCROLL_REGION_OK (frame) ? 0 : lines_below);
|
154
|
102 /* first_insert_cost[I] is the cost of doing the first insert-line
|
25004
|
103 at the i'th line of the lines we are considering,
|
154
|
104 where I is origin 1 (as it is below). */
|
|
105 int *first_insert_cost
|
51212
|
106 = &FRAME_INSERT_COST (frame)[frame_lines - 1 - lines_moved];
|
154
|
107 int *first_delete_cost
|
51212
|
108 = &FRAME_DELETE_COST (frame)[frame_lines - 1 - lines_moved];
|
154
|
109 int *next_insert_cost
|
51212
|
110 = &FRAME_INSERTN_COST (frame)[frame_lines - 1 - lines_moved];
|
154
|
111 int *next_delete_cost
|
51212
|
112 = &FRAME_DELETEN_COST (frame)[frame_lines - 1 - lines_moved];
|
154
|
113
|
|
114 /* Discourage long scrolls on fast lines.
|
766
|
115 Don't scroll nearly a full frame height unless it saves
|
154
|
116 at least 1/4 second. */
|
110550
|
117 int extra_cost = (int) (baud_rate / (10 * 4 * FRAME_LINES (frame)));
|
154
|
118
|
3356
|
119 if (baud_rate <= 0)
|
|
120 extra_cost = 1;
|
|
121
|
154
|
122 /* initialize the top left corner of the matrix */
|
|
123 matrix->writecost = 0;
|
|
124 matrix->insertcost = INFINITY;
|
|
125 matrix->deletecost = INFINITY;
|
|
126 matrix->insertcount = 0;
|
|
127 matrix->deletecount = 0;
|
|
128
|
|
129 /* initialize the left edge of the matrix */
|
|
130 cost = first_insert_cost[1] - next_insert_cost[1];
|
|
131 for (i = 1; i <= window_size; i++)
|
|
132 {
|
|
133 p = matrix + i * (window_size + 1);
|
|
134 cost += draw_cost[i] + next_insert_cost[i] + extra_cost;
|
|
135 p->insertcost = cost;
|
|
136 p->writecost = INFINITY;
|
|
137 p->deletecost = INFINITY;
|
|
138 p->insertcount = i;
|
|
139 p->deletecount = 0;
|
|
140 }
|
|
141
|
|
142 /* initialize the top edge of the matrix */
|
|
143 cost = first_delete_cost[1] - next_delete_cost[1];
|
|
144 for (j = 1; j <= window_size; j++)
|
|
145 {
|
|
146 cost += next_delete_cost[j];
|
|
147 matrix[j].deletecost = cost;
|
|
148 matrix[j].writecost = INFINITY;
|
|
149 matrix[j].insertcost = INFINITY;
|
|
150 matrix[j].deletecount = j;
|
|
151 matrix[j].insertcount = 0;
|
|
152 }
|
|
153
|
766
|
154 /* `i' represents the vpos among new frame contents.
|
|
155 `j' represents the vpos among the old frame contents. */
|
154
|
156 p = matrix + window_size + 2; /* matrix [1, 1] */
|
|
157 for (i = 1; i <= window_size; i++, p++)
|
|
158 for (j = 1; j <= window_size; j++, p++)
|
|
159 {
|
|
160 /* p contains the address of matrix [i, j] */
|
|
161
|
|
162 /* First calculate the cost assuming we do
|
|
163 not insert or delete above this line.
|
|
164 That is, if we update through line i-1
|
|
165 based on old lines through j-1,
|
|
166 and then just change old line j to new line i. */
|
|
167 p1 = p - window_size - 2; /* matrix [i-1, j-1] */
|
|
168 cost = p1->writecost;
|
|
169 if (cost > p1->insertcost)
|
|
170 cost = p1->insertcost;
|
|
171 if (cost > p1->deletecost)
|
|
172 cost = p1->deletecost;
|
|
173 if (old_hash[j] != new_hash[i])
|
|
174 cost += draw_cost[i];
|
|
175 p->writecost = cost;
|
|
176
|
|
177 /* Calculate the cost if we do an insert-line
|
|
178 before outputting this line.
|
|
179 That is, we update through line i-1
|
|
180 based on old lines through j,
|
|
181 do an insert-line on line i,
|
|
182 and then output line i from scratch,
|
|
183 leaving old lines starting from j for reuse below. */
|
|
184 p1 = p - window_size - 1; /* matrix [i-1, j] */
|
|
185 /* No need to think about doing a delete followed
|
|
186 immediately by an insert. It cannot be as good
|
|
187 as not doing either of them. */
|
|
188 if (free_at_end == i)
|
|
189 {
|
|
190 cost = p1->writecost;
|
|
191 cost1 = p1->insertcost;
|
|
192 }
|
|
193 else
|
|
194 {
|
|
195 cost = p1->writecost + first_insert_cost[i];
|
6888
|
196 if ((int) p1->insertcount > i)
|
154
|
197 abort ();
|
|
198 cost1 = p1->insertcost + next_insert_cost[i - p1->insertcount];
|
|
199 }
|
|
200 p->insertcost = min (cost, cost1) + draw_cost[i] + extra_cost;
|
|
201 p->insertcount = (cost < cost1) ? 1 : p1->insertcount + 1;
|
6888
|
202 if ((int) p->insertcount > i)
|
154
|
203 abort ();
|
|
204
|
|
205 /* Calculate the cost if we do a delete line after
|
|
206 outputting this line.
|
|
207 That is, we update through line i
|
|
208 based on old lines through j-1,
|
|
209 and throw away old line j. */
|
|
210 p1 = p - 1; /* matrix [i, j-1] */
|
|
211 /* No need to think about doing an insert followed
|
|
212 immediately by a delete. */
|
|
213 if (free_at_end == i)
|
|
214 {
|
|
215 cost = p1->writecost;
|
|
216 cost1 = p1->deletecost;
|
|
217 }
|
|
218 else
|
|
219 {
|
|
220 cost = p1->writecost + first_delete_cost[i];
|
|
221 cost1 = p1->deletecost + next_delete_cost[i];
|
|
222 }
|
|
223 p->deletecost = min (cost, cost1);
|
|
224 p->deletecount = (cost < cost1) ? 1 : p1->deletecount + 1;
|
|
225 }
|
|
226 }
|
25004
|
227
|
|
228
|
154
|
229
|
25004
|
230 /* Perform insert-lines and delete-lines operations on CURRENT_MATRIX
|
|
231 according to the costs in MATRIX, using the general scrolling
|
|
232 method that is used if the terminal does not support the setting of
|
49600
|
233 scroll windows (scroll_region_ok == 0).
|
6647
|
234
|
|
235 WINDOW_SIZE is the number of lines being considered for scrolling
|
25004
|
236 and UNCHANGED_AT_TOP is the vpos of the first line being
|
|
237 considered. These two arguments can specify any contiguous range
|
|
238 of lines. */
|
49600
|
239
|
154
|
240 static void
|
109126
|
241 do_scrolling (struct frame *frame, struct glyph_matrix *current_matrix, struct matrix_elt *matrix, int window_size, int unchanged_at_top)
|
154
|
242 {
|
25004
|
243 struct matrix_elt *p;
|
|
244 int i, j, k;
|
|
245
|
|
246 /* Set to 1 if we have set a terminal window with
|
|
247 set_terminal_window. */
|
|
248 int terminal_window_p = 0;
|
154
|
249
|
25004
|
250 /* A queue for line insertions to be done. */
|
|
251 struct queue { int count, pos; };
|
|
252 struct queue *queue_start
|
|
253 = (struct queue *) alloca (current_matrix->nrows * sizeof (struct queue));
|
|
254 struct queue *queue = queue_start;
|
49600
|
255
|
25004
|
256 char *retained_p = (char *) alloca (window_size * sizeof (char));
|
|
257 int *copy_from = (int *) alloca (window_size * sizeof (int));
|
154
|
258
|
25004
|
259 /* Zero means line is empty. */
|
109165
750db9f3e6d8
Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
Andreas Schwab <schwab@linux-m68k.org>
diff
changeset
|
260 memset (retained_p, 0, window_size * sizeof (char));
|
25004
|
261 for (k = 0; k < window_size; ++k)
|
|
262 copy_from[k] = -1;
|
154
|
263
|
28407
|
264 #define CHECK_BOUNDS \
|
25004
|
265 do \
|
|
266 { \
|
|
267 int k; \
|
|
268 for (k = 0; k < window_size; ++k) \
|
|
269 xassert (copy_from[k] == -1 \
|
|
270 || (copy_from[k] >= 0 && copy_from[k] < window_size)); \
|
|
271 } \
|
|
272 while (0);
|
154
|
273
|
25004
|
274 /* When j is advanced, this corresponds to deleted lines.
|
|
275 When i is advanced, this corresponds to inserted lines. */
|
154
|
276 i = j = window_size;
|
|
277 while (i > 0 || j > 0)
|
|
278 {
|
|
279 p = matrix + i * (window_size + 1) + j;
|
49600
|
280
|
25004
|
281 if (p->insertcost < p->writecost && p->insertcost < p->deletecost)
|
154
|
282 {
|
25004
|
283 /* Insert should be done at vpos i-1, plus maybe some before.
|
|
284 Queue the screen operation to be performed. */
|
|
285 queue->count = p->insertcount;
|
|
286 queue->pos = i + unchanged_at_top - p->insertcount;
|
|
287 ++queue;
|
|
288
|
|
289 /* By incrementing I, we leave room in the result rows
|
|
290 for the empty rows opened up. */
|
154
|
291 i -= p->insertcount;
|
|
292 }
|
|
293 else if (p->deletecost < p->writecost)
|
|
294 {
|
25004
|
295 /* Old line at vpos j-1, and maybe some before it, should be
|
|
296 deleted. By decrementing J, we skip some lines in the
|
|
297 temp_rows which is equivalent to omitting these lines in
|
|
298 the result rows, thus deleting them. */
|
154
|
299 j -= p->deletecount;
|
25004
|
300
|
|
301 /* Set the terminal window, if not done already. */
|
|
302 if (! terminal_window_p)
|
154
|
303 {
|
83100
|
304 set_terminal_window (frame, window_size + unchanged_at_top);
|
25004
|
305 terminal_window_p = 1;
|
154
|
306 }
|
25004
|
307
|
|
308 /* Delete lines on the terminal. */
|
83100
|
309 ins_del_lines (frame, j + unchanged_at_top, - p->deletecount);
|
154
|
310 }
|
|
311 else
|
|
312 {
|
25004
|
313 /* Best thing done here is no insert or delete, i.e. a write. */
|
|
314 --i, --j;
|
|
315 xassert (i >= 0 && i < window_size);
|
|
316 xassert (j >= 0 && j < window_size);
|
|
317 copy_from[i] = j;
|
|
318 retained_p[j] = 1;
|
154
|
319
|
25004
|
320 #if GLYPH_DEBUG
|
28407
|
321 CHECK_BOUNDS;
|
25004
|
322 #endif
|
154
|
323 }
|
|
324 }
|
|
325
|
25004
|
326 /* Now do all insertions queued above. */
|
|
327 if (queue > queue_start)
|
154
|
328 {
|
25004
|
329 int next = -1;
|
|
330
|
|
331 /* Set the terminal window if not yet done. */
|
|
332 if (!terminal_window_p)
|
|
333 {
|
83100
|
334 set_terminal_window (frame, window_size + unchanged_at_top);
|
25004
|
335 terminal_window_p = 1;
|
|
336 }
|
|
337
|
|
338 do
|
|
339 {
|
|
340 --queue;
|
|
341
|
|
342 /* Do the deletion on the terminal. */
|
83100
|
343 ins_del_lines (frame, queue->pos, queue->count);
|
25004
|
344
|
|
345 /* All lines in the range deleted become empty in the glyph
|
|
346 matrix. Assign to them glyph rows that are not retained.
|
|
347 K is the starting position of the deleted range relative
|
|
348 to the window we are working in. */
|
|
349 k = queue->pos - unchanged_at_top;
|
|
350 for (j = 0; j < queue->count; ++j)
|
|
351 {
|
|
352 /* Find the next row not retained. */
|
|
353 while (retained_p[++next])
|
|
354 ;
|
|
355
|
|
356 /* Record that this row is to be used for the empty
|
|
357 glyph row j. */
|
|
358 copy_from[k + j] = next;
|
|
359 }
|
|
360 }
|
|
361 while (queue > queue_start);
|
49600
|
362
|
154
|
363 }
|
|
364
|
25004
|
365 for (k = 0; k < window_size; ++k)
|
|
366 xassert (copy_from[k] >= 0 && copy_from[k] < window_size);
|
154
|
367
|
25004
|
368 /* Perform the row swizzling. */
|
|
369 mirrored_line_dance (current_matrix, unchanged_at_top, window_size,
|
|
370 copy_from, retained_p);
|
154
|
371
|
25004
|
372 /* Some sanity checks if GLYPH_DEBUG != 0. */
|
|
373 CHECK_MATRIX (current_matrix);
|
49600
|
374
|
25004
|
375 if (terminal_window_p)
|
83100
|
376 set_terminal_window (frame, 0);
|
154
|
377 }
|
25004
|
378
|
154
|
379
|
10262
|
380 /* Determine, in matrix[i,j], the cost of updating the first j
|
|
381 old lines into the first i new lines using the direct
|
|
382 scrolling method. When the old line and the new line have
|
|
383 different hash codes, the calculated cost of updating old
|
|
384 line j into new line i includes the cost of outputting new
|
|
385 line i, and if i != j, the cost of outputting the old line j
|
|
386 is also included, as a penalty for moving the line and then
|
|
387 erasing it. In addition, the cost of updating a sequence of
|
|
388 lines with constant i - j includes the cost of scrolling the
|
|
389 old lines into their new positions, unless i == j. Scrolling
|
|
390 is achieved by setting the screen window to avoid affecting
|
|
391 other lines below, and inserting or deleting lines at the top
|
|
392 of the scrolled region. The cost of scrolling a sequence of
|
|
393 lines includes the fixed cost of specifying a scroll region,
|
|
394 plus a variable cost which can depend upon the number of lines
|
|
395 involved and the distance by which they are scrolled, and an
|
|
396 extra cost to discourage long scrolls.
|
|
397
|
|
398 As reflected in the matrix, an insert or delete does not
|
|
399 correspond directly to the insertion or deletion which is
|
|
400 used in scrolling lines. An insert means that the value of i
|
|
401 has increased without a corresponding increase in the value
|
|
402 of j. A delete means that the value of j has increased
|
|
403 without a corresponding increase in the value of i. A write
|
|
404 means that i and j are both increased by the same amount, and
|
|
405 that the old lines will be moved to their new positions.
|
|
406
|
|
407 An insert following a delete is allowed only if i > j.
|
|
408 A delete following an insert is allowed only if i < j.
|
|
409 These restrictions ensure that the new lines in an insert
|
|
410 will always be blank as an effect of the neighboring writes.
|
|
411 Thus the calculated cost of an insert is simply the cost of
|
|
412 outputting the new line contents. The direct cost of a
|
|
413 delete is zero. Inserts and deletes indirectly affect the
|
|
414 total cost through their influence on subsequent writes. */
|
|
415
|
|
416 /* The vectors draw_cost, old_hash, and new_hash have the same
|
|
417 meanings here as in calculate_scrolling, and old_draw_cost
|
|
418 is the equivalent of draw_cost for the old line contents */
|
|
419
|
|
420 static void
|
109139
|
421 calculate_direct_scrolling (FRAME_PTR frame,
|
|
422 /* matrix is of size window_size + 1 on each side. */
|
|
423 struct matrix_elt *matrix,
|
|
424 int window_size, int lines_below,
|
|
425 int *draw_cost, int *old_draw_cost,
|
|
426 int *old_hash, int *new_hash,
|
|
427 int free_at_end)
|
10262
|
428 {
|
|
429 register int i, j;
|
110550
|
430 EMACS_INT frame_lines = FRAME_LINES (frame);
|
10262
|
431 register struct matrix_elt *p, *p1;
|
|
432 register int cost, cost1, delta;
|
|
433
|
|
434 /* first_insert_cost[-I] is the cost of doing the first insert-line
|
|
435 at a position I lines above the bottom line in the scroll window. */
|
|
436 int *first_insert_cost
|
51212
|
437 = &FRAME_INSERT_COST (frame)[frame_lines - 1];
|
10262
|
438 int *first_delete_cost
|
51212
|
439 = &FRAME_DELETE_COST (frame)[frame_lines - 1];
|
10262
|
440 int *next_insert_cost
|
51212
|
441 = &FRAME_INSERTN_COST (frame)[frame_lines - 1];
|
10262
|
442 int *next_delete_cost
|
51212
|
443 = &FRAME_DELETEN_COST (frame)[frame_lines - 1];
|
10262
|
444
|
|
445 int scroll_overhead;
|
|
446
|
|
447 /* Discourage long scrolls on fast lines.
|
|
448 Don't scroll nearly a full frame height unless it saves
|
|
449 at least 1/4 second. */
|
110550
|
450 int extra_cost = (int) (baud_rate / (10 * 4 * FRAME_LINES (frame)));
|
10262
|
451
|
|
452 if (baud_rate <= 0)
|
|
453 extra_cost = 1;
|
|
454
|
|
455 /* Overhead of setting the scroll window, plus the extra cost
|
|
456 cost of scrolling by a distance of one. The extra cost is
|
|
457 added once for consistency with the cost vectors */
|
53225
|
458 scroll_overhead
|
82990
2ecd1f669db9
Fixed X support, preliminary support for X-tty combo sessions.
Karoly Lorentey <lorentey@elte.hu>
diff
changeset
|
459 = FRAME_SCROLL_REGION_COST (frame) + extra_cost;
|
10262
|
460
|
|
461 /* initialize the top left corner of the matrix */
|
|
462 matrix->writecost = 0;
|
|
463 matrix->insertcost = INFINITY;
|
|
464 matrix->deletecost = INFINITY;
|
|
465 matrix->writecount = 0;
|
|
466 matrix->insertcount = 0;
|
|
467 matrix->deletecount = 0;
|
|
468
|
|
469 /* initialize the left edge of the matrix */
|
|
470 cost = 0;
|
|
471 for (i = 1; i <= window_size; i++)
|
|
472 {
|
|
473 p = matrix + i * (window_size + 1);
|
|
474 cost += draw_cost[i];
|
|
475 p->insertcost = cost;
|
|
476 p->writecost = INFINITY;
|
|
477 p->deletecost = INFINITY;
|
|
478 p->insertcount = i;
|
|
479 p->writecount = 0;
|
|
480 p->deletecount = 0;
|
|
481 }
|
|
482
|
|
483 /* initialize the top edge of the matrix */
|
|
484 for (j = 1; j <= window_size; j++)
|
|
485 {
|
|
486 matrix[j].deletecost = 0;
|
|
487 matrix[j].writecost = INFINITY;
|
|
488 matrix[j].insertcost = INFINITY;
|
|
489 matrix[j].deletecount = j;
|
|
490 matrix[j].writecount = 0;
|
|
491 matrix[j].insertcount = 0;
|
|
492 }
|
|
493
|
|
494 /* `i' represents the vpos among new frame contents.
|
|
495 `j' represents the vpos among the old frame contents. */
|
|
496 p = matrix + window_size + 2; /* matrix [1, 1] */
|
|
497
|
|
498 for (i = 1; i <= window_size; i++, p++)
|
|
499 for (j = 1; j <= window_size; j++, p++)
|
|
500 {
|
|
501 /* p contains the address of matrix [i, j] */
|
|
502
|
|
503 /* First calculate the cost assuming we do
|
|
504 not insert or delete above this line.
|
|
505 That is, if we update through line i-1
|
|
506 based on old lines through j-1,
|
|
507 and then just change old line j to new line i.
|
|
508
|
|
509 Depending on which choice gives the lower cost,
|
|
510 this usually involves either scrolling a single line
|
|
511 or extending a sequence of scrolled lines, but
|
|
512 when i == j, no scrolling is required. */
|
|
513 p1 = p - window_size - 2; /* matrix [i-1, j-1] */
|
|
514 cost = p1->insertcost;
|
|
515 if (cost > p1->deletecost)
|
|
516 cost = p1->deletecost;
|
|
517 cost1 = p1->writecost;
|
|
518 if (i == j)
|
|
519 {
|
|
520 if (cost > cost1)
|
|
521 {
|
|
522 cost = cost1;
|
|
523 p->writecount = p1->writecount + 1;
|
|
524 }
|
|
525 else
|
|
526 p->writecount = 1;
|
|
527 if (old_hash[j] != new_hash[i])
|
|
528 {
|
|
529 cost += draw_cost[i];
|
|
530 }
|
|
531 }
|
|
532 else
|
|
533 {
|
|
534 if (i > j)
|
|
535 {
|
|
536 delta = i - j;
|
|
537
|
|
538 /* The cost added here for scrolling the first line by
|
|
539 a distance N includes the overhead of setting the
|
|
540 scroll window, the cost of inserting N lines at a
|
|
541 position N lines above the bottom line of the window,
|
|
542 and an extra cost which is proportional to N. */
|
|
543 cost += scroll_overhead + first_insert_cost[-delta] +
|
|
544 (delta-1) * (next_insert_cost[-delta] + extra_cost);
|
|
545
|
|
546 /* In the most general case, the insertion overhead and
|
|
547 the multiply factor can grow linearly as the distance
|
|
548 from the bottom of the window increases. The incremental
|
|
549 cost of scrolling an additional line depends upon the
|
|
550 rate of change of these two parameters. Each of these
|
|
551 growth rates can be determined by a simple difference.
|
|
552 To reduce the cumulative effects of rounding error, we
|
|
553 vary the position at which the difference is computed. */
|
|
554 cost1 += first_insert_cost[-j] - first_insert_cost[1-j] +
|
49600
|
555 (delta-1) * (next_insert_cost[-j] - next_insert_cost[1-j]);
|
10262
|
556 }
|
|
557 else
|
|
558 {
|
|
559 delta = j - i;
|
|
560 cost += scroll_overhead + first_delete_cost[-delta] +
|
|
561 (delta-1) * (next_delete_cost[-delta] + extra_cost);
|
|
562 cost1 += first_delete_cost[-i] - first_delete_cost[1-i] +
|
49600
|
563 (delta-1) * ( next_delete_cost[-i] - next_delete_cost[1-i]);
|
10262
|
564 }
|
|
565 if (cost1 < cost)
|
|
566 {
|
|
567 cost = cost1;
|
|
568 p->writecount = p1->writecount + 1;
|
|
569 }
|
|
570 else
|
|
571 p->writecount = 1;
|
|
572 if (old_hash[j] != new_hash[i])
|
|
573 {
|
|
574 cost += draw_cost[i] + old_draw_cost[j];
|
|
575 }
|
|
576 }
|
|
577 p->writecost = cost;
|
|
578
|
|
579 /* Calculate the cost if we do an insert-line
|
|
580 before outputting this line.
|
|
581 That is, we update through line i-1
|
|
582 based on old lines through j,
|
|
583 do an insert-line on line i,
|
|
584 and then output line i from scratch,
|
|
585 leaving old lines starting from j for reuse below. */
|
|
586 p1 = p - window_size - 1; /* matrix [i-1, j] */
|
|
587 cost = p1->writecost;
|
|
588 /* If i > j, an insert is allowed after a delete. */
|
|
589 if (i > j && p1->deletecost < cost)
|
|
590 cost = p1->deletecost;
|
|
591 if (p1->insertcost <= cost)
|
|
592 {
|
|
593 cost = p1->insertcost;
|
|
594 p->insertcount = p1->insertcount + 1;
|
|
595 }
|
|
596 else
|
|
597 p->insertcount = 1;
|
|
598 cost += draw_cost[i];
|
|
599 p->insertcost = cost;
|
|
600
|
|
601 /* Calculate the cost if we do a delete line after
|
|
602 outputting this line.
|
|
603 That is, we update through line i
|
|
604 based on old lines through j-1,
|
|
605 and throw away old line j. */
|
|
606 p1 = p - 1; /* matrix [i, j-1] */
|
|
607 cost = p1->writecost;
|
|
608 /* If i < j, a delete is allowed after an insert. */
|
|
609 if (i < j && p1->insertcost < cost)
|
|
610 cost = p1->insertcost;
|
|
611 cost1 = p1->deletecost;
|
|
612 if (p1->deletecost <= cost)
|
|
613 {
|
|
614 cost = p1->deletecost;
|
|
615 p->deletecount = p1->deletecount + 1;
|
|
616 }
|
|
617 else
|
|
618 p->deletecount = 1;
|
|
619 p->deletecost = cost;
|
|
620 }
|
|
621 }
|
25004
|
622
|
|
623
|
10262
|
624
|
25004
|
625 /* Perform insert-lines and delete-lines operations on CURRENT_MATRIX
|
|
626 according to the costs in MATRIX, using the direct scrolling method
|
|
627 which is used when the terminal supports setting a scroll window
|
|
628 (scroll_region_ok).
|
10262
|
629
|
|
630 WINDOW_SIZE is the number of lines being considered for scrolling
|
25004
|
631 and UNCHANGED_AT_TOP is the vpos of the first line being
|
|
632 considered. These two arguments can specify any contiguous range
|
|
633 of lines.
|
49600
|
634
|
10262
|
635 In the direct scrolling method, a new scroll window is selected
|
|
636 before each insertion or deletion, so that groups of lines can be
|
|
637 scrolled directly to their final vertical positions. This method
|
25004
|
638 is described in more detail in calculate_direct_scrolling, where
|
|
639 the cost matrix for this approach is constructed. */
|
10262
|
640
|
|
641 static void
|
109360
|
642 do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
|
|
643 struct matrix_elt *cost_matrix, int window_size,
|
|
644 int unchanged_at_top)
|
10262
|
645 {
|
25004
|
646 struct matrix_elt *p;
|
|
647 int i, j;
|
|
648
|
|
649 /* A queue of deletions and insertions to be performed. */
|
|
650 struct alt_queue { int count, pos, window; };
|
|
651 struct alt_queue *queue_start = (struct alt_queue *)
|
|
652 alloca (window_size * sizeof *queue_start);
|
|
653 struct alt_queue *queue = queue_start;
|
|
654
|
|
655 /* Set to 1 if a terminal window has been set with
|
|
656 set_terminal_window: */
|
|
657 int terminal_window_p = 0;
|
10262
|
658
|
|
659 /* A nonzero value of write_follows indicates that a write has been
|
25004
|
660 selected, allowing either an insert or a delete to be selected
|
|
661 next. When write_follows is zero, a delete cannot be selected
|
|
662 unless j < i, and an insert cannot be selected unless i < j.
|
|
663 This corresponds to a similar restriction (with the ordering
|
|
664 reversed) in calculate_direct_scrolling, which is intended to
|
|
665 ensure that lines marked as inserted will be blank. */
|
|
666 int write_follows_p = 1;
|
10262
|
667
|
25004
|
668 /* For each row in the new matrix what row of the old matrix it is. */
|
|
669 int *copy_from = (int *) alloca (window_size * sizeof (int));
|
10262
|
670
|
25004
|
671 /* Non-zero for each row in the new matrix that is retained from the
|
|
672 old matrix. Lines not retained are empty. */
|
|
673 char *retained_p = (char *) alloca (window_size * sizeof (char));
|
10262
|
674
|
109165
750db9f3e6d8
Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
Andreas Schwab <schwab@linux-m68k.org>
diff
changeset
|
675 memset (retained_p, 0, window_size * sizeof (char));
|
25004
|
676
|
|
677 /* Perform some sanity checks when GLYPH_DEBUG is on. */
|
|
678 CHECK_MATRIX (current_matrix);
|
10262
|
679
|
25004
|
680 /* We are working on the line range UNCHANGED_AT_TOP ...
|
|
681 UNCHANGED_AT_TOP + WINDOW_SIZE (not including) in CURRENT_MATRIX.
|
|
682 We step through lines in this range from the end to the start. I
|
|
683 is an index into new lines, j an index into old lines. The cost
|
|
684 matrix determines what to do for ranges of indices.
|
10262
|
685
|
25004
|
686 If i is decremented without also decrementing j, this corresponds
|
|
687 to inserting empty lines in the result. If j is decremented
|
|
688 without also decrementing i, this corresponds to omitting these
|
|
689 lines in the new rows, i.e. rows are deleted. */
|
10262
|
690 i = j = window_size;
|
49600
|
691
|
10262
|
692 while (i > 0 || j > 0)
|
|
693 {
|
25004
|
694 p = cost_matrix + i * (window_size + 1) + j;
|
49600
|
695
|
25004
|
696 if (p->insertcost < p->writecost
|
|
697 && p->insertcost < p->deletecost
|
|
698 && (write_follows_p || i < j))
|
10262
|
699 {
|
25004
|
700 /* Insert is cheaper than deleting or writing lines. Leave
|
|
701 a hole in the result display that will be filled with
|
|
702 empty lines when the queue is emptied. */
|
|
703 queue->count = 0;
|
|
704 queue->window = i;
|
|
705 queue->pos = i - p->insertcount;
|
|
706 ++queue;
|
49600
|
707
|
10262
|
708 i -= p->insertcount;
|
25004
|
709 write_follows_p = 0;
|
10262
|
710 }
|
25004
|
711 else if (p->deletecost < p->writecost
|
|
712 && (write_follows_p || i > j))
|
10262
|
713 {
|
25004
|
714 /* Deleting lines is cheaper. By decrementing J, omit
|
|
715 deletecount lines from the original. */
|
|
716 write_follows_p = 0;
|
10262
|
717 j -= p->deletecount;
|
|
718 }
|
|
719 else
|
|
720 {
|
25004
|
721 /* One or more lines should be written. In the direct
|
|
722 scrolling method we do this by scrolling the lines to the
|
|
723 place they belong. */
|
|
724 int n_to_write = p->writecount;
|
|
725 write_follows_p = 1;
|
49600
|
726 xassert (n_to_write > 0);
|
25004
|
727
|
10262
|
728 if (i > j)
|
|
729 {
|
25004
|
730 /* Immediately insert lines */
|
83100
|
731 set_terminal_window (frame, i + unchanged_at_top);
|
25004
|
732 terminal_window_p = 1;
|
83100
|
733 ins_del_lines (frame, j - n_to_write + unchanged_at_top, i - j);
|
10262
|
734 }
|
|
735 else if (i < j)
|
|
736 {
|
25004
|
737 /* Queue the deletion of a group of lines */
|
|
738 queue->pos = i - n_to_write + unchanged_at_top;
|
|
739 queue->window = j + unchanged_at_top;
|
|
740 queue->count = i - j;
|
|
741 ++queue;
|
10262
|
742 }
|
|
743
|
25004
|
744 while (n_to_write > 0)
|
10262
|
745 {
|
25004
|
746 --i, --j, --n_to_write;
|
|
747 copy_from[i] = j;
|
|
748 retained_p[j] = 1;
|
10262
|
749 }
|
|
750 }
|
|
751 }
|
|
752
|
25004
|
753 /* Do queued operations. */
|
|
754 if (queue > queue_start)
|
|
755 {
|
|
756 int next = -1;
|
10262
|
757
|
25004
|
758 do
|
10262
|
759 {
|
25004
|
760 --queue;
|
|
761 if (queue->count)
|
10262
|
762 {
|
83100
|
763 set_terminal_window (frame, queue->window);
|
25004
|
764 terminal_window_p = 1;
|
83100
|
765 ins_del_lines (frame, queue->pos, queue->count);
|
25004
|
766 }
|
|
767 else
|
|
768 {
|
|
769 for (j = queue->window - 1; j >= queue->pos; --j)
|
|
770 {
|
|
771 while (retained_p[++next])
|
|
772 ;
|
|
773 copy_from[j] = next;
|
|
774 }
|
10262
|
775 }
|
|
776 }
|
25004
|
777 while (queue > queue_start);
|
10262
|
778 }
|
|
779
|
25004
|
780 /* Now, for each row I in the range of rows we are working on,
|
|
781 copy_from[i] gives the original line to copy to I, and
|
|
782 retained_p[copy_from[i]] is zero if line I in the new display is
|
|
783 empty. */
|
|
784 mirrored_line_dance (current_matrix, unchanged_at_top, window_size,
|
|
785 copy_from, retained_p);
|
|
786
|
|
787 if (terminal_window_p)
|
83100
|
788 set_terminal_window (frame, 0);
|
10262
|
789 }
|
25004
|
790
|
|
791
|
10262
|
792
|
154
|
793 void
|
109360
|
794 scrolling_1 (FRAME_PTR frame, int window_size, int unchanged_at_top,
|
|
795 int unchanged_at_bottom, int *draw_cost, int *old_draw_cost,
|
|
796 int *old_hash, int *new_hash, int free_at_end)
|
154
|
797 {
|
|
798 struct matrix_elt *matrix;
|
|
799 matrix = ((struct matrix_elt *)
|
|
800 alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix));
|
|
801
|
82990
2ecd1f669db9
Fixed X support, preliminary support for X-tty combo sessions.
Karoly Lorentey <lorentey@elte.hu>
diff
changeset
|
802 if (FRAME_SCROLL_REGION_OK (frame))
|
10262
|
803 {
|
|
804 calculate_direct_scrolling (frame, matrix, window_size,
|
|
805 unchanged_at_bottom,
|
49600
|
806 draw_cost, old_draw_cost,
|
10262
|
807 old_hash, new_hash, free_at_end);
|
83100
|
808 do_direct_scrolling (frame, frame->current_matrix,
|
25004
|
809 matrix, window_size, unchanged_at_top);
|
10262
|
810 }
|
|
811 else
|
|
812 {
|
|
813 calculate_scrolling (frame, matrix, window_size, unchanged_at_bottom,
|
|
814 draw_cost, old_hash, new_hash,
|
|
815 free_at_end);
|
83100
|
816 do_scrolling (frame,
|
|
817 frame->current_matrix, matrix, window_size,
|
25004
|
818 unchanged_at_top);
|
10262
|
819 }
|
154
|
820 }
|
25004
|
821
|
|
822
|
154
|
823
|
25004
|
824 /* Return number of lines in common between current and desired frame
|
|
825 contents described to us only as vectors of hash codes OLDHASH and
|
|
826 NEWHASH. Consider only vpos range START to END (not including
|
|
827 END). Ignore short lines on the assumption that avoiding redrawing
|
|
828 such a line will have little weight. */
|
154
|
829
|
|
830 int
|
109126
|
831 scrolling_max_lines_saved (int start, int end, int *oldhash, int *newhash, int *cost)
|
154
|
832 {
|
|
833 struct { int hash; int count; } lines[01000];
|
|
834 register int i, h;
|
|
835 register int matchcount = 0;
|
|
836 int avg_length = 0;
|
|
837 int threshold;
|
|
838
|
|
839 /* Compute a threshold which is 1/4 of average length of these lines. */
|
|
840
|
|
841 for (i = start; i < end; i++)
|
|
842 avg_length += cost[i];
|
|
843
|
|
844 avg_length /= end - start;
|
|
845 threshold = avg_length / 4;
|
|
846
|
109165
750db9f3e6d8
Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
Andreas Schwab <schwab@linux-m68k.org>
diff
changeset
|
847 memset (lines, 0, sizeof lines);
|
154
|
848
|
25004
|
849 /* Put new lines' hash codes in hash table. Ignore lines shorter
|
|
850 than the threshold. Thus, if the lines that are in common are
|
|
851 mainly the ones that are short, they won't count. */
|
154
|
852 for (i = start; i < end; i++)
|
|
853 {
|
|
854 if (cost[i] > threshold)
|
|
855 {
|
|
856 h = newhash[i] & 0777;
|
|
857 lines[h].hash = newhash[i];
|
|
858 lines[h].count++;
|
|
859 }
|
|
860 }
|
|
861
|
25004
|
862 /* Look up old line hash codes in the hash table. Count number of
|
|
863 matches between old lines and new. */
|
154
|
864 for (i = start; i < end; i++)
|
|
865 {
|
|
866 h = oldhash[i] & 0777;
|
|
867 if (oldhash[i] == lines[h].hash)
|
|
868 {
|
|
869 matchcount++;
|
|
870 if (--lines[h].count == 0)
|
|
871 lines[h].hash = 0;
|
|
872 }
|
|
873 }
|
|
874
|
|
875 return matchcount;
|
|
876 }
|
|
877
|
25004
|
878 /* Return a measure of the cost of moving the lines starting with vpos
|
|
879 FROM, up to but not including vpos TO, down by AMOUNT lines (AMOUNT
|
|
880 may be negative). These are the same arguments that might be given
|
|
881 to scroll_frame_lines to perform this scrolling. */
|
154
|
882
|
21514
|
883 int
|
109126
|
884 scroll_cost (FRAME_PTR frame, int from, int to, int amount)
|
154
|
885 {
|
766
|
886 /* Compute how many lines, at bottom of frame,
|
154
|
887 will not be involved in actual motion. */
|
110550
|
888 EMACS_INT limit = to;
|
|
889 EMACS_INT offset;
|
|
890 EMACS_INT height = FRAME_LINES (frame);
|
154
|
891
|
421
|
892 if (amount == 0)
|
|
893 return 0;
|
|
894
|
82990
2ecd1f669db9
Fixed X support, preliminary support for X-tty combo sessions.
Karoly Lorentey <lorentey@elte.hu>
diff
changeset
|
895 if (! FRAME_SCROLL_REGION_OK (frame))
|
154
|
896 limit = height;
|
421
|
897 else if (amount > 0)
|
|
898 limit += amount;
|
154
|
899
|
|
900 if (amount < 0)
|
|
901 {
|
|
902 int temp = to;
|
|
903 to = from + amount;
|
|
904 from = temp + amount;
|
|
905 amount = - amount;
|
|
906 }
|
|
907
|
|
908 offset = height - limit;
|
|
909
|
|
910 return
|
766
|
911 (FRAME_INSERT_COST (frame)[offset + from]
|
|
912 + (amount - 1) * FRAME_INSERTN_COST (frame)[offset + from]
|
10109
869e177ca872
(scroll_cost): FRAME_DELETE_COST and FRAME_DELETEN_COSTS were confused. Fixed.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
913 + FRAME_DELETE_COST (frame)[offset + to]
|
869e177ca872
(scroll_cost): FRAME_DELETE_COST and FRAME_DELETEN_COSTS were confused. Fixed.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
914 + (amount - 1) * FRAME_DELETEN_COST (frame)[offset + to]);
|
154
|
915 }
|
|
916
|
|
917 /* Calculate the line insertion/deletion
|
|
918 overhead and multiply factor values */
|
|
919
|
|
920 static void
|
109126
|
921 line_ins_del (FRAME_PTR frame, int ov1, int pf1, int ovn, int pfn, register int *ov, register int *mf)
|
154
|
922 {
|
110550
|
923 register EMACS_INT i;
|
|
924 register EMACS_INT frame_lines = FRAME_LINES (frame);
|
154
|
925 register int insert_overhead = ov1 * 10;
|
|
926 register int next_insert_cost = ovn * 10;
|
|
927
|
51212
|
928 for (i = frame_lines-1; i >= 0; i--)
|
154
|
929 {
|
529
|
930 mf[i] = next_insert_cost / 10;
|
154
|
931 next_insert_cost += pfn;
|
529
|
932 ov[i] = (insert_overhead + next_insert_cost) / 10;
|
154
|
933 insert_overhead += pf1;
|
|
934 }
|
|
935 }
|
|
936
|
|
937 static void
|
109139
|
938 ins_del_costs (FRAME_PTR frame,
|
|
939 char *one_line_string, char *multi_string,
|
|
940 char *setup_string, char *cleanup_string,
|
|
941 int *costvec, int *ncostvec,
|
|
942 int coefficient)
|
154
|
943 {
|
|
944 if (multi_string)
|
766
|
945 line_ins_del (frame,
|
154
|
946 string_cost (multi_string) * coefficient,
|
|
947 per_line_cost (multi_string) * coefficient,
|
|
948 0, 0, costvec, ncostvec);
|
|
949 else if (one_line_string)
|
766
|
950 line_ins_del (frame,
|
154
|
951 string_cost (setup_string) + string_cost (cleanup_string), 0,
|
|
952 string_cost (one_line_string),
|
|
953 per_line_cost (one_line_string),
|
|
954 costvec, ncostvec);
|
|
955 else
|
766
|
956 line_ins_del (frame,
|
154
|
957 9999, 0, 9999, 0,
|
|
958 costvec, ncostvec);
|
|
959 }
|
|
960
|
|
961 /* Calculate the insert and delete line costs.
|
|
962 Note that this is done even when running with a window system
|
|
963 because we want to know how long scrolling takes (and avoid it).
|
766
|
964 This must be redone whenever the frame height changes.
|
154
|
965
|
|
966 We keep the ID costs in a precomputed array based on the position
|
|
967 at which the I or D is performed. Also, there are two kinds of ID
|
|
968 costs: the "once-only" and the "repeated". This is to handle both
|
|
969 those terminals that are able to insert N lines at a time (once-
|
|
970 only) and those that must repeatedly insert one line.
|
|
971
|
|
972 The cost to insert N lines at line L is
|
51212
|
973 [tt.t_ILov + (frame_lines + 1 - L) * tt.t_ILpf] +
|
|
974 N * [tt.t_ILnov + (frame_lines + 1 - L) * tt.t_ILnpf]
|
154
|
975
|
|
976 ILov represents the basic insert line overhead. ILpf is the padding
|
|
977 required to allow the terminal time to move a line: insertion at line
|
51212
|
978 L changes (frame_lines + 1 - L) lines.
|
154
|
979
|
|
980 The first bracketed expression above is the overhead; the second is
|
|
981 the multiply factor. Both are dependent only on the position at
|
|
982 which the insert is performed. We store the overhead in
|
766
|
983 FRAME_INSERT_COST (frame) and the multiply factor in
|
|
984 FRAME_INSERTN_COST (frame). Note however that any insertion
|
154
|
985 must include at least one multiply factor. Rather than compute this
|
766
|
986 as FRAME_INSERT_COST (frame)[line]+FRAME_INSERTN_COST (frame)[line],
|
|
987 we add FRAME_INSERTN_COST (frame) into FRAME_INSERT_COST (frame).
|
154
|
988 This is reasonable because of the particular algorithm used in calcM.
|
|
989
|
|
990 Deletion is essentially the same as insertion.
|
|
991 */
|
|
992
|
21514
|
993 void
|
109364
|
994 do_line_insertion_deletion_costs (FRAME_PTR frame,
|
|
995 char *ins_line_string, char *multi_ins_string,
|
|
996 char *del_line_string, char *multi_del_string,
|
|
997 char *setup_string, char *cleanup_string,
|
|
998 int coefficient)
|
154
|
999 {
|
766
|
1000 if (FRAME_INSERT_COST (frame) != 0)
|
154
|
1001 {
|
766
|
1002 FRAME_INSERT_COST (frame) =
|
|
1003 (int *) xrealloc (FRAME_INSERT_COST (frame),
|
51212
|
1004 FRAME_LINES (frame) * sizeof (int));
|
766
|
1005 FRAME_DELETEN_COST (frame) =
|
|
1006 (int *) xrealloc (FRAME_DELETEN_COST (frame),
|
51212
|
1007 FRAME_LINES (frame) * sizeof (int));
|
766
|
1008 FRAME_INSERTN_COST (frame) =
|
|
1009 (int *) xrealloc (FRAME_INSERTN_COST (frame),
|
51212
|
1010 FRAME_LINES (frame) * sizeof (int));
|
766
|
1011 FRAME_DELETE_COST (frame) =
|
|
1012 (int *) xrealloc (FRAME_DELETE_COST (frame),
|
51212
|
1013 FRAME_LINES (frame) * sizeof (int));
|
154
|
1014 }
|
|
1015 else
|
|
1016 {
|
766
|
1017 FRAME_INSERT_COST (frame) =
|
51212
|
1018 (int *) xmalloc (FRAME_LINES (frame) * sizeof (int));
|
766
|
1019 FRAME_DELETEN_COST (frame) =
|
51212
|
1020 (int *) xmalloc (FRAME_LINES (frame) * sizeof (int));
|
766
|
1021 FRAME_INSERTN_COST (frame) =
|
51212
|
1022 (int *) xmalloc (FRAME_LINES (frame) * sizeof (int));
|
49600
|
1023 FRAME_DELETE_COST (frame) =
|
51212
|
1024 (int *) xmalloc (FRAME_LINES (frame) * sizeof (int));
|
154
|
1025 }
|
|
1026
|
766
|
1027 ins_del_costs (frame,
|
154
|
1028 ins_line_string, multi_ins_string,
|
|
1029 setup_string, cleanup_string,
|
766
|
1030 FRAME_INSERT_COST (frame), FRAME_INSERTN_COST (frame),
|
154
|
1031 coefficient);
|
766
|
1032 ins_del_costs (frame,
|
154
|
1033 del_line_string, multi_del_string,
|
|
1034 setup_string, cleanup_string,
|
9576
|
1035 FRAME_DELETE_COST (frame), FRAME_DELETEN_COST (frame),
|
154
|
1036 coefficient);
|
|
1037 }
|
52401
|
1038
|
|
1039 /* arch-tag: cdb7149c-48e7-4793-a948-2786c8e45485
|
|
1040 (do not change this comment) */
|