aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dispnew.c289
1 files changed, 187 insertions, 102 deletions
diff --git a/src/dispnew.c b/src/dispnew.c
index da538cc658e..c0176a59abc 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -4217,6 +4217,120 @@ set_window_cursor_after_update (w)
4217} 4217}
4218 4218
4219 4219
4220/* Set WINDOW->must_be_updated_p to ON_P for all windows in the window
4221 tree rooted at W. */
4222
4223void
4224set_window_update_flags (w, on_p)
4225 struct window *w;
4226 int on_p;
4227{
4228 while (w)
4229 {
4230 if (!NILP (w->hchild))
4231 set_window_update_flags (XWINDOW (w->hchild), on_p);
4232 else if (!NILP (w->vchild))
4233 set_window_update_flags (XWINDOW (w->vchild), on_p);
4234 else
4235 w->must_be_updated_p = on_p;
4236
4237 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4238 }
4239}
4240
4241
4242
4243/***********************************************************************
4244 Window-Based Scrolling
4245 ***********************************************************************/
4246
4247/* Structure describing rows in scrolling_window. */
4248
4249struct row_entry
4250{
4251 /* Number of occurrences of this row in desired and current matrix. */
4252 int old_uses, new_uses;
4253
4254 /* Vpos of row in new matrix. */
4255 int new_line_number;
4256
4257 /* Bucket index of this row_entry in the hash table row_table. */
4258 int bucket;
4259
4260 /* The row described by this entry. */
4261 struct glyph_row *row;
4262
4263 /* Hash collision chain. */
4264 struct row_entry *next;
4265};
4266
4267/* A pool to allocate row_entry structures from, and the size of the
4268 pool. The pool is reallocated in scrolling_window when we find
4269 that we need a larger one. */
4270
4271static struct row_entry *row_entry_pool;
4272static int row_entry_pool_size;
4273
4274/* Index of next free entry in row_entry_pool. */
4275
4276static int row_entry_idx;
4277
4278/* The hash table used during scrolling, and the table's size. This
4279 table is used to quickly identify equal rows in the desired and
4280 current matrix. */
4281
4282static struct row_entry **row_table;
4283static int row_table_size;
4284
4285/* Vectors of pointers to row_entry structures belonging to the
4286 current and desired matrix, and the size of the vectors. */
4287
4288static struct row_entry **old_lines, **new_lines;
4289static int old_lines_size, new_lines_size;
4290
4291/* A pool to allocate run structures from, and its size. */
4292
4293static struct run *run_pool;
4294static int runs_size;
4295
4296/* A vector of runs of lines found during scrolling. */
4297
4298static struct run **runs;
4299
4300static struct row_entry *add_row_entry P_ ((struct window *,
4301 struct glyph_row *));
4302
4303
4304/* Add glyph row ROW to the scrolling hash table during the scrolling
4305 of window W. */
4306
4307static INLINE struct row_entry *
4308add_row_entry (w, row)
4309 struct window *w;
4310 struct glyph_row *row;
4311{
4312 struct row_entry *entry;
4313 int i = row->hash % row_table_size;
4314
4315 entry = row_table[i];
4316 while (entry && !row_equal_p (w, entry->row, row))
4317 entry = entry->next;
4318
4319 if (entry == NULL)
4320 {
4321 entry = row_entry_pool + row_entry_idx++;
4322 entry->row = row;
4323 entry->old_uses = entry->new_uses = 0;
4324 entry->new_line_number = 0;
4325 entry->bucket = i;
4326 entry->next = row_table[i];
4327 row_table[i] = entry;
4328 }
4329
4330 return entry;
4331}
4332
4333
4220/* Try to reuse part of the current display of W by scrolling lines. 4334/* Try to reuse part of the current display of W by scrolling lines.
4221 HEADER_LINE_P non-zero means W has a top mode line. 4335 HEADER_LINE_P non-zero means W has a top mode line.
4222 4336
@@ -4248,39 +4362,20 @@ scrolling_window (w, header_line_p)
4248 struct window *w; 4362 struct window *w;
4249 int header_line_p; 4363 int header_line_p;
4250{ 4364{
4251 struct symbol
4252 {
4253 /* Number of occurrences of this line in old and new matrix. */
4254 short old_uses, new_uses;
4255
4256 /* Vpos of line in new matrix. */
4257 short new_line_number;
4258
4259 /* The line itself. */
4260 struct glyph_row *row;
4261
4262 /* Hash collision chain. */
4263 struct symbol *next;
4264 };
4265
4266 int SYMBOL_TABLE_SIZE = 101;
4267 struct symbol **table;
4268 struct symbol **old_line_syms, **new_line_syms;
4269 int i, j, first_old, first_new, last_old, last_new;
4270 struct symbol *sym;
4271 struct run **runs;
4272 int nruns;
4273 struct glyph_matrix *desired_matrix = w->desired_matrix; 4365 struct glyph_matrix *desired_matrix = w->desired_matrix;
4274 struct glyph_matrix *current_matrix = w->current_matrix; 4366 struct glyph_matrix *current_matrix = w->current_matrix;
4275 int yb = window_text_bottom_y (w); 4367 int yb = window_text_bottom_y (w);
4368 int i, j, first_old, first_new, last_old, last_new;
4369 int nruns, nbytes, n, run_idx;
4370 struct row_entry *entry;
4276 4371
4277 /* Skip over rows equal at the start. */ 4372 /* Skip over rows equal at the start. */
4278 i = header_line_p ? 1 : 0; 4373 i = header_line_p ? 1 : 0;
4279 while (i < current_matrix->nrows - 1 4374 while (i < current_matrix->nrows - 1
4280 && MATRIX_ROW_ENABLED_P (current_matrix, i) 4375 && MATRIX_ROW_ENABLED_P (current_matrix, i)
4281 && MATRIX_ROW_ENABLED_P (desired_matrix, i) 4376 && MATRIX_ROW_ENABLED_P (desired_matrix, i)
4282 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb 4377 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) <= yb
4283 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb 4378 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) <= yb
4284 && row_equal_p (w, 4379 && row_equal_p (w,
4285 MATRIX_ROW (desired_matrix, i), 4380 MATRIX_ROW (desired_matrix, i),
4286 MATRIX_ROW (current_matrix, i))) 4381 MATRIX_ROW (current_matrix, i)))
@@ -4302,7 +4397,7 @@ scrolling_window (w, header_line_p)
4302 i = first_new + 1; 4397 i = first_new + 1;
4303 while (i < desired_matrix->nrows - 1 4398 while (i < desired_matrix->nrows - 1
4304 && MATRIX_ROW (desired_matrix, i)->enabled_p 4399 && MATRIX_ROW (desired_matrix, i)->enabled_p
4305 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb) 4400 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) <= yb)
4306 ++i; 4401 ++i;
4307 4402
4308 if (!MATRIX_ROW (desired_matrix, i)->enabled_p) 4403 if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
@@ -4316,7 +4411,7 @@ scrolling_window (w, header_line_p)
4316 disabled. */ 4411 disabled. */
4317 i = first_old + 1; 4412 i = first_old + 1;
4318 while (i < current_matrix->nrows - 1 4413 while (i < current_matrix->nrows - 1
4319 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb) 4414 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) <= yb)
4320 ++i; 4415 ++i;
4321 last_old = i; 4416 last_old = i;
4322 4417
@@ -4339,76 +4434,84 @@ scrolling_window (w, header_line_p)
4339 if (last_new == first_new) 4434 if (last_new == first_new)
4340 return 0; 4435 return 0;
4341 4436
4342 /* Allocate a hash table in which all rows will be inserted. */ 4437 /* Reallocate vectors, tables etc. if necessary. */
4343 table = (struct symbol **) alloca (SYMBOL_TABLE_SIZE * sizeof *table); 4438
4344 bzero (table, SYMBOL_TABLE_SIZE * sizeof *table); 4439 if (current_matrix->nrows > old_lines_size)
4345 4440 {
4346 /* For each row in the current matrix, record the symbol belonging 4441 old_lines_size = current_matrix->nrows;
4347 to the row in OLD_LINE_SYMS. */ 4442 nbytes = old_lines_size * sizeof *old_lines;
4348 old_line_syms = (struct symbol **) alloca (current_matrix->nrows 4443 old_lines = (struct row_entry **) xrealloc (old_lines, nbytes);
4349 * sizeof *old_line_syms); 4444 }
4350 new_line_syms = (struct symbol **) alloca (desired_matrix->nrows 4445
4351 * sizeof *new_line_syms); 4446 if (desired_matrix->nrows > new_lines_size)
4352 4447 {
4353#define ADDSYM(ROW) \ 4448 new_lines_size = desired_matrix->nrows;
4354 do \ 4449 nbytes = new_lines_size * sizeof *new_lines;
4355 { \ 4450 new_lines = (struct row_entry **) xrealloc (new_lines, nbytes);
4356 struct glyph_row *row_ = (ROW); \ 4451 }
4357 int i_ = row_->hash % SYMBOL_TABLE_SIZE; \ 4452
4358 sym = table[i_]; \ 4453 n = desired_matrix->nrows + current_matrix->nrows;
4359 while (sym && !row_equal_p (w, sym->row, row_)) \ 4454 if (3 * n > row_table_size)
4360 sym = sym->next; \ 4455 {
4361 if (sym == NULL) \ 4456 row_table_size = next_almost_prime (3 * n);
4362 { \ 4457 nbytes = row_table_size * sizeof *row_table;
4363 sym = (struct symbol *) alloca (sizeof *sym); \ 4458 row_table = (struct row_entry **) xrealloc (row_table, nbytes);
4364 sym->row = row_; \ 4459 bzero (row_table, nbytes);
4365 sym->old_uses = sym->new_uses = 0; \ 4460 }
4366 sym->next = table[i_]; \ 4461
4367 table[i_] = sym; \ 4462 if (n > row_entry_pool_size)
4368 } \ 4463 {
4369 } \ 4464 row_entry_pool_size = n;
4370 while (0) 4465 nbytes = row_entry_pool_size * sizeof *row_entry_pool;
4371 4466 row_entry_pool = (struct row_entry *) xrealloc (row_entry_pool, nbytes);
4372 /* Add current rows to the symbol table. */ 4467 }
4468
4469 if (desired_matrix->nrows > runs_size)
4470 {
4471 runs_size = desired_matrix->nrows;
4472 nbytes = runs_size * sizeof *runs;
4473 runs = (struct run **) xrealloc (runs, nbytes);
4474 nbytes = runs_size * sizeof *run_pool;
4475 run_pool = (struct run *) xrealloc (run_pool, nbytes);
4476 }
4477
4478 nruns = run_idx = 0;
4479 row_entry_idx = 0;
4480
4481 /* Add rows from the current and desired matrix to the hash table
4482 row_hash_table to be able to find equal ones quickly. */
4483
4373 for (i = first_old; i < last_old; ++i) 4484 for (i = first_old; i < last_old; ++i)
4374 { 4485 {
4375 if (MATRIX_ROW (current_matrix, i)->enabled_p) 4486 if (MATRIX_ROW (current_matrix, i)->enabled_p)
4376 { 4487 {
4377 ADDSYM (MATRIX_ROW (current_matrix, i)); 4488 entry = add_row_entry (w, MATRIX_ROW (current_matrix, i));
4378 old_line_syms[i] = sym; 4489 old_lines[i] = entry;
4379 ++sym->old_uses; 4490 ++entry->old_uses;
4380 } 4491 }
4381 else 4492 else
4382 old_line_syms[i] = NULL; 4493 old_lines[i] = NULL;
4383 } 4494 }
4384 4495
4385 /* Add desired rows to the symbol table. */
4386 for (i = first_new; i < last_new; ++i) 4496 for (i = first_new; i < last_new; ++i)
4387 { 4497 {
4388 xassert (MATRIX_ROW_ENABLED_P (desired_matrix, i)); 4498 xassert (MATRIX_ROW_ENABLED_P (desired_matrix, i));
4389 ADDSYM (MATRIX_ROW (desired_matrix, i)); 4499 entry = add_row_entry (w, MATRIX_ROW (desired_matrix, i));
4390 ++sym->new_uses; 4500 ++entry->new_uses;
4391 new_line_syms[i] = sym; 4501 entry->new_line_number = i;
4392 sym->new_line_number = i; 4502 new_lines[i] = entry;
4393 } 4503 }
4394 4504
4395#undef ADDSYM
4396
4397 /* Record in runs which moves were found, ordered by pixel
4398 height of copied areas. */
4399 nruns = 0;
4400 runs = (struct run **) alloca (desired_matrix->nrows * sizeof *runs);
4401
4402 /* Identify moves based on lines that are unique and equal 4505 /* Identify moves based on lines that are unique and equal
4403 in both matrices. */ 4506 in both matrices. */
4404 for (i = first_old; i < last_old;) 4507 for (i = first_old; i < last_old;)
4405 if (old_line_syms[i] 4508 if (old_lines[i]
4406 && old_line_syms[i]->old_uses == 1 4509 && old_lines[i]->old_uses == 1
4407 && old_line_syms[i]->new_uses == 1) 4510 && old_lines[i]->new_uses == 1)
4408 { 4511 {
4409 int j, k; 4512 int j, k;
4410 int new_line = old_line_syms[i]->new_line_number; 4513 int new_line = old_lines[i]->new_line_number;
4411 struct run *run = (struct run *) alloca (sizeof *run); 4514 struct run *run = run_pool + run_idx++;
4412 4515
4413 /* Record move. */ 4516 /* Record move. */
4414 run->current_vpos = i; 4517 run->current_vpos = i;
@@ -4423,7 +4526,7 @@ scrolling_window (w, header_line_p)
4423 k = new_line - 1; 4526 k = new_line - 1;
4424 while (j > first_old 4527 while (j > first_old
4425 && k > first_new 4528 && k > first_new
4426 && old_line_syms[j] == new_line_syms[k]) 4529 && old_lines[j] == new_lines[k])
4427 { 4530 {
4428 int h = MATRIX_ROW (current_matrix, j)->height; 4531 int h = MATRIX_ROW (current_matrix, j)->height;
4429 --run->current_vpos; 4532 --run->current_vpos;
@@ -4440,7 +4543,7 @@ scrolling_window (w, header_line_p)
4440 k = new_line + 1; 4543 k = new_line + 1;
4441 while (j < last_old 4544 while (j < last_old
4442 && k < last_new 4545 && k < last_new
4443 && old_line_syms[j] == new_line_syms[k]) 4546 && old_lines[j] == new_lines[k])
4444 { 4547 {
4445 int h = MATRIX_ROW (current_matrix, j)->height; 4548 int h = MATRIX_ROW (current_matrix, j)->height;
4446 ++run->nrows; 4549 ++run->nrows;
@@ -4518,33 +4621,15 @@ scrolling_window (w, header_line_p)
4518 } 4621 }
4519 } 4622 }
4520 4623
4624 /* Clear the hash table, for the next time. */
4625 for (i = 0; i < row_entry_idx; ++i)
4626 row_table[row_entry_pool[i].bucket] = NULL;
4627
4521 /* Value is non-zero to indicate that we scrolled the display. */ 4628 /* Value is non-zero to indicate that we scrolled the display. */
4522 return 1; 4629 return 1;
4523} 4630}
4524 4631
4525 4632
4526/* Set WINDOW->must_be_updated_p TO ON_P for all windows WINDOW in the
4527 window tree rooted at W. */
4528
4529void
4530set_window_update_flags (w, on_p)
4531 struct window *w;
4532 int on_p;
4533{
4534 while (w)
4535 {
4536 if (!NILP (w->hchild))
4537 set_window_update_flags (XWINDOW (w->hchild), on_p);
4538 else if (!NILP (w->vchild))
4539 set_window_update_flags (XWINDOW (w->vchild), on_p);
4540 else
4541 w->must_be_updated_p = on_p;
4542
4543 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4544 }
4545}
4546
4547
4548 4633
4549/************************************************************************ 4634/************************************************************************
4550 Frame-Based Updates 4635 Frame-Based Updates