|
Lines 476-540
struct canvas *cv;
Link Here
|
| 476 |
free(cv); |
476 |
free(cv); |
| 477 |
} |
477 |
} |
| 478 |
|
478 |
|
|
|
479 |
struct canvas * |
| 480 |
get_new_canvas(target) |
| 481 |
struct canvas *target; |
| 482 |
{ /** Allocate a new canvas, and assign it characteristics |
| 483 |
equal to those of target. */ |
| 484 |
struct canvas *cv; |
| 485 |
|
| 486 |
if ((cv = (struct canvas *) calloc(1, sizeof *cv)) == 0) |
| 487 |
return NULL; |
| 488 |
|
| 489 |
cv -> c_xs = target -> c_xs; |
| 490 |
cv -> c_xe = target -> c_xe; |
| 491 |
cv -> c_ys = target -> c_ys; |
| 492 |
cv -> c_ye = target -> c_ye; |
| 493 |
cv -> c_xoff = target -> c_xoff; |
| 494 |
cv -> c_yoff = target -> c_yoff; |
| 495 |
cv -> c_display = target -> c_display; |
| 496 |
cv -> c_vplist = 0; |
| 497 |
cv -> c_captev.type = EV_TIMEOUT; |
| 498 |
cv -> c_captev.data = (char *) cv; |
| 499 |
cv -> c_captev.handler = cv_winid_fn; |
| 500 |
|
| 501 |
cv -> c_blank.l_cvlist = cv; |
| 502 |
cv -> c_blank.l_width = cv->c_xe - cv->c_xs + 1; |
| 503 |
cv -> c_blank.l_height = cv->c_ye - cv->c_ys + 1; |
| 504 |
cv -> c_blank.l_x = cv->c_blank.l_y = 0; |
| 505 |
cv -> c_blank.l_layfn = &BlankLf; |
| 506 |
cv -> c_blank.l_data = 0; |
| 507 |
cv -> c_blank.l_next = 0; |
| 508 |
cv -> c_blank.l_bottom = &cv->c_blank; |
| 509 |
cv -> c_blank.l_blocking = 0; |
| 510 |
cv -> c_layer = &cv->c_blank; |
| 511 |
cv -> c_lnext = 0; |
| 512 |
|
| 513 |
cv -> c_left = target -> c_left; |
| 514 |
cv -> c_right = target -> c_right; |
| 515 |
cv -> c_above = target -> c_above; |
| 516 |
cv -> c_below = target -> c_below; |
| 517 |
|
| 518 |
return cv; |
| 519 |
} |
| 520 |
|
| 479 |
int |
521 |
int |
| 480 |
AddCanvas() |
522 |
share_limits( type, cv0, cv1) |
| 481 |
{ |
523 |
int type; /* HORIZONTAL or VERTICAL */ |
| 482 |
int hh, h, i, j; |
524 |
struct canvas *cv0; /* canvas to compare against. */ |
| 483 |
struct canvas *cv, **cvpp; |
525 |
struct canvas *cv1; /* canvas to compare against. */ |
|
|
526 |
{ /** Return non-zero if the two canvasses share limits. |
| 527 |
(ie, their horizontal or veritcal boundaries are the same) |
| 528 |
*/ |
| 529 |
switch (type) { |
| 530 |
case HORIZONTAL: |
| 531 |
return cv0 -> c_xs == cv1 -> c_xs && cv0->c_xe == cv1 -> c_xe; |
| 532 |
case VERTICAL: |
| 533 |
return cv0 -> c_ys == cv1 -> c_ys && cv0->c_ye == cv1 -> c_ye; |
| 534 |
} |
| 535 |
ASSERT(0); |
| 536 |
return 0; |
| 537 |
} |
| 484 |
|
538 |
|
| 485 |
for (cv = D_cvlist, j = 0; cv; cv = cv->c_next) |
539 |
int |
| 486 |
j++; |
540 |
compute_region(type, a, focus, list) |
| 487 |
j++; /* new canvas */ |
541 |
int type; /* 0 - horizontal, 1 - vertical */ |
| 488 |
h = D_height - (D_has_hstatus == HSTATUS_LASTLINE); |
542 |
struct screen_region *a; /* Return value. */ |
| 489 |
if (h / j <= 1) |
543 |
struct canvas *focus; /* Canvas to compute around. */ |
| 490 |
return -1; |
544 |
struct canvas *list; /* List of all canvasses. */ |
|
|
545 |
{ /** Find the start and end of the screen region.*/ |
| 546 |
/* |
| 547 |
I'm using the term 'region' here differently |
| 548 |
than elsewhere. Elsewhere, 'region' is synonymous |
| 549 |
with 'canvas', but I am using it to denote |
| 550 |
a collection of related canvasses. |
| 491 |
|
551 |
|
| 492 |
for (cv = D_cvlist; cv; cv = cv->c_next) |
552 |
Suppose the screen currently looks |
| 493 |
if (cv == D_forecv) |
553 |
like this: |
|
|
554 |
--------------------------- |
| 555 |
| 0 | 1 | 2 | |
| 556 |
--------------------------- |
| 557 |
| 3 | 4 | 5 | |
| 558 |
--------------------------- |
| 559 |
| 6 | |
| 560 |
--------------------------- |
| 561 |
| 7 | 8 | 9 | |
| 562 |
--------------------------- |
| 563 |
Where there are 10 entries in D_cvlist. |
| 564 |
Canvasses 0,1,2 are in the same region, as |
| 565 |
are cavasses 1 and 4. We need to be careful not to |
| 566 |
lump 1 and 4 together w/8. The |
| 567 |
type of the region containing 0,1,2 is |
| 568 |
VERTICAL, since each canvas is created |
| 569 |
via a vertical split. |
| 570 |
|
| 571 |
Throughout, I'm assuming that canvasses |
| 572 |
are created so that any region will |
| 573 |
be contiguous in D_cvlist. |
| 574 |
|
| 575 |
Note: this was written before the screen |
| 576 |
orientation members (c_left, c_above, c_below, |
| 577 |
c_right) were added to the struct canvas. |
| 578 |
Might want to rewrite this to use those. |
| 579 |
|
| 580 |
Written by Bill Pursell, 23/12/2005 |
| 581 |
*/ |
| 582 |
|
| 583 |
struct canvas *cv; /* Entry in list. */ |
| 584 |
int seen_focus; /* Flag used when walking the list. */ |
| 585 |
|
| 586 |
seen_focus = 0; |
| 587 |
a->count = 0; |
| 588 |
a->type = type; |
| 589 |
|
| 590 |
if (type == HORIZONTAL) { |
| 591 |
a->xs = focus -> c_xs; |
| 592 |
a->xe = focus -> c_xe; |
| 593 |
a->ys = -1; |
| 594 |
} |
| 595 |
if (type == VERTICAL) { |
| 596 |
a->ys = focus -> c_ys; |
| 597 |
a->ye = focus -> c_ye; |
| 598 |
a->xs = -1; |
| 599 |
} |
| 600 |
/* Count the canvasses in the same region as the |
| 601 |
canvas with the focus, and find the limits of the region. */ |
| 602 |
for (cv = list; cv; cv = cv->c_next) { |
| 603 |
if (cv == focus) |
| 604 |
seen_focus = 1; |
| 605 |
if (share_limits( type, cv, focus)) { |
| 606 |
debug2("cv = %x %s\n", cv, (cv == focus)? "FORE":""); |
| 607 |
debug2("x range: %d - %d\n", cv->c_xs, cv->c_xe); |
| 608 |
debug2("y range: %d - %d\n", cv->c_ys, cv->c_ye); |
| 609 |
switch (type) { |
| 610 |
case HORIZONTAL : |
| 611 |
if (a->ys == -1) { |
| 612 |
a->ys = cv -> c_ys; |
| 613 |
a->start = cv; |
| 614 |
} |
| 615 |
a->ye = cv -> c_ye; |
| 494 |
break; |
616 |
break; |
| 495 |
ASSERT(cv); |
617 |
case VERTICAL: |
| 496 |
cvpp = &cv->c_next; |
618 |
if (a->xs == -1) { |
|
|
619 |
a->xs = cv -> c_xs; |
| 620 |
a->start = cv; |
| 621 |
} |
| 622 |
a->xe = cv -> c_xe; |
| 623 |
break; |
| 624 |
} |
| 497 |
|
625 |
|
| 498 |
if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0) |
626 |
a->end = cv; |
| 499 |
return -1; |
627 |
a->count++; |
|
|
628 |
} |
| 629 |
if (!share_limits(type, cv, focus) || cv -> c_next == NULL) { |
| 630 |
if (seen_focus) { |
| 631 |
debug2("x range of Region: %d-%d\n", a->xs, a->xe); |
| 632 |
debug2("y range of Region: %d-%d\n", a->ys, a->ye); |
| 633 |
break; |
| 634 |
} |
| 635 |
else { |
| 636 |
switch(type) { |
| 637 |
case HORIZONTAL: a->ys = -1; break; |
| 638 |
case VERTICAL : a->xs = -1; break; |
| 639 |
} |
| 640 |
a->count = 0; |
| 641 |
} |
| 642 |
} |
| 643 |
} |
| 500 |
|
644 |
|
| 501 |
cv->c_xs = 0; |
645 |
switch (type) { |
| 502 |
cv->c_xe = D_width - 1; |
646 |
case HORIZONTAL: |
| 503 |
cv->c_ys = 0; |
647 |
a->expanse = a->ye - a->ys + 1; |
| 504 |
cv->c_ye = D_height - 1; |
648 |
ASSERT(a->expanse <= D_height - (D_has_hstatus == HSTATUS_LASTLINE)); |
| 505 |
cv->c_xoff = 0; |
649 |
break; |
| 506 |
cv->c_yoff = 0; |
650 |
case VERTICAL: |
| 507 |
cv->c_display = display; |
651 |
a->expanse = a->xe - a->xs + 1; |
| 508 |
cv->c_vplist = 0; |
652 |
ASSERT(a->expanse <= D_width); |
| 509 |
cv->c_captev.type = EV_TIMEOUT; |
653 |
break; |
| 510 |
cv->c_captev.data = (char *)cv; |
654 |
} |
| 511 |
cv->c_captev.handler = cv_winid_fn; |
655 |
ASSERT(seen_focus); |
|
|
656 |
} |
| 512 |
|
657 |
|
| 513 |
cv->c_blank.l_cvlist = cv; |
658 |
void |
| 514 |
cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1; |
659 |
reset_region_types(region, type) |
| 515 |
cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1; |
660 |
struct screen_region *region; |
| 516 |
cv->c_blank.l_x = cv->c_blank.l_y = 0; |
661 |
int type; |
| 517 |
cv->c_blank.l_layfn = &BlankLf; |
662 |
{ /** Set c_type of all the canvasses in the region to type. */ |
| 518 |
cv->c_blank.l_data = 0; |
|
|
| 519 |
cv->c_blank.l_next = 0; |
| 520 |
cv->c_blank.l_bottom = &cv->c_blank; |
| 521 |
cv->c_blank.l_blocking = 0; |
| 522 |
cv->c_layer = &cv->c_blank; |
| 523 |
cv->c_lnext = 0; |
| 524 |
|
663 |
|
| 525 |
cv->c_next = *cvpp; |
664 |
struct canvas *cv; |
| 526 |
*cvpp = cv; |
|
|
| 527 |
|
665 |
|
| 528 |
i = 0; |
666 |
for (cv = region->start; cv != region->end->c_next; cv = cv->c_next) { |
| 529 |
for (cv = D_cvlist; cv; cv = cv->c_next) |
667 |
#ifdef DEBUG |
| 530 |
{ |
668 |
switch(type) { |
| 531 |
hh = h / j-- - 1; |
669 |
case HORIZONTAL: |
| 532 |
cv->c_ys = i; |
670 |
ASSERT (cv->c_xs == region -> xs && cv->c_xe == region -> xe); |
| 533 |
cv->c_ye = i + hh - 1; |
671 |
break; |
| 534 |
cv->c_yoff = i; |
672 |
case VERTICAL: |
| 535 |
i += hh + 1; |
673 |
ASSERT (cv->c_ys == region -> ys && cv->c_ye == region -> ye); |
| 536 |
h -= hh + 1; |
674 |
break; |
|
|
675 |
default: |
| 676 |
ASSERT(0); |
| 677 |
} |
| 678 |
#endif |
| 679 |
cv -> c_type = type; |
| 537 |
} |
680 |
} |
|
|
681 |
} |
| 682 |
|
| 683 |
void |
| 684 |
debug_print_canvas(cv) |
| 685 |
struct canvas *cv; |
| 686 |
{ /** Print cv to the debug file. */ |
| 687 |
#ifdef DEBUG |
| 688 |
debug2("%x %s\n", cv, (cv == D_forecv)?" HAS FOCUS":""); |
| 689 |
debug2(" above: %x below: %x\n", cv->c_above, cv->c_below); |
| 690 |
debug2(" left: %x right: %x\n", cv->c_left, cv->c_right); |
| 691 |
debug3(" x range: %2d-%2d, xoff = %d\n", |
| 692 |
cv->c_xs, cv->c_xe, cv->c_xoff); |
| 693 |
debug3(" y range: %2d-%2d yoff = %d\n", |
| 694 |
cv->c_ys, cv->c_ye, cv->c_yoff); |
| 695 |
debug2(" next: %x type: %d\n", cv->c_next, cv->c_type); |
| 696 |
#endif |
| 697 |
} |
| 698 |
|
| 699 |
void |
| 700 |
debug_print_all_canvasses(header) |
| 701 |
char *header; |
| 702 |
{ /** Print the dimensions of all the canvasses |
| 703 |
in the current display to the debug file. Precede |
| 704 |
with a line containing the header message. */ |
| 705 |
#ifdef DEBUG |
| 706 |
struct canvas *cv; |
| 707 |
char message[BUFSIZ]; |
| 708 |
|
| 709 |
sprintf(message, "%10s %5d: ",__FILE__ , __LINE__); |
| 710 |
strcat (message, header); |
| 711 |
fprintf(dfp, message); |
| 712 |
fflush(dfp); |
| 713 |
for (cv = D_cvlist; cv; cv = cv->c_next) { |
| 714 |
debug_print_canvas(cv); |
| 715 |
} |
| 716 |
#endif |
| 717 |
return; |
| 718 |
} |
| 719 |
|
| 720 |
set_internal_orientation(region) |
| 721 |
struct screen_region *region; |
| 722 |
{ /** Set the orientation for canvasses inside the region. */ |
| 723 |
|
| 724 |
struct canvas *cv; |
| 725 |
|
| 726 |
for (cv = region -> start; cv != region -> end; cv = cv->c_next) { |
| 727 |
ASSERT (cv -> c_type == region -> type); |
| 728 |
switch (region->type) { |
| 729 |
case VERTICAL: |
| 730 |
cv -> c_right = cv -> c_next; |
| 731 |
cv -> c_next -> c_left = cv; |
| 732 |
break; |
| 733 |
case HORIZONTAL: |
| 734 |
cv -> c_below = cv -> c_next; |
| 735 |
cv -> c_next -> c_above = cv; |
| 736 |
break; |
| 737 |
} |
| 738 |
} |
| 739 |
} |
| 740 |
|
| 741 |
|
| 742 |
int |
| 743 |
AddCanvas(type) |
| 744 |
int type; /* Horizontal or Vertical. */ |
| 745 |
{ /** Add a new canvas, via a split. */ |
| 746 |
|
| 747 |
struct canvas *cv; /* Index into D_cvlist. */ |
| 748 |
struct screen_region vr; /* Canvasses in the same row/column as the |
| 749 |
canvas with the focus. */ |
| 750 |
|
| 751 |
compute_region(type, &vr, D_forecv, D_cvlist); |
| 752 |
|
| 753 |
/* Return if the region isn't big enough to split. */ |
| 754 |
if (vr.expanse / vr.count <= 1) |
| 755 |
return -1; |
| 756 |
|
| 757 |
/* Allocate a new canvas. */ |
| 758 |
if ( (cv = get_new_canvas(D_forecv)) == NULL) |
| 759 |
return -1; |
| 760 |
|
| 761 |
/* Set the type. */ |
| 762 |
cv -> c_type = D_forecv -> c_type = type; |
| 763 |
|
| 764 |
/* Increment the canvas count to account for the one we will add. */ |
| 765 |
vr.count++; |
| 766 |
|
| 767 |
debug_print_all_canvasses("AddCanvas start.\n"); |
| 768 |
|
| 769 |
/* Insert the new canvas after the current foreground. */ |
| 770 |
cv -> c_next = D_forecv->c_next; |
| 771 |
D_forecv -> c_next = cv; |
| 772 |
if (vr.end == D_forecv) |
| 773 |
vr.end = cv; |
| 774 |
|
| 775 |
set_internal_orientation(&vr); |
| 776 |
equalize_canvas_dimensions(&vr); |
| 777 |
|
| 778 |
debug_print_all_canvasses("AddCanvas end.\n"); |
| 538 |
|
779 |
|
| 539 |
RethinkDisplayViewports(); |
780 |
RethinkDisplayViewports(); |
| 540 |
ResizeLayersToCanvases(); |
781 |
ResizeLayersToCanvases(); |
|
Lines 542-608
AddCanvas()
Link Here
|
| 542 |
} |
783 |
} |
| 543 |
|
784 |
|
| 544 |
void |
785 |
void |
| 545 |
RemCanvas() |
786 |
get_endpoints(cv, start, end, off) |
|
|
787 |
struct canvas *cv; |
| 788 |
int **start; |
| 789 |
int **end; |
| 790 |
int **off; |
| 791 |
{ /** Set *start, *end, and *off appropriate with cv->c_type. */ |
| 792 |
switch (cv->c_type) { |
| 793 |
case HORIZONTAL: |
| 794 |
if (start) *start = &cv -> c_ys; |
| 795 |
if (end) *end = &cv -> c_ye; |
| 796 |
if (off) *off = &cv -> c_yoff; |
| 797 |
break; |
| 798 |
case VERTICAL: |
| 799 |
if (start) *start = &cv -> c_xs; |
| 800 |
if (end) *end = &cv -> c_xe; |
| 801 |
if (off) *off = &cv -> c_xoff; |
| 802 |
break; |
| 803 |
default: ASSERT(0); |
| 804 |
} |
| 805 |
} |
| 806 |
|
| 807 |
#define MIN_HEIGHT 1 |
| 808 |
#define MIN_WIDTH 5 |
| 809 |
|
| 810 |
int |
| 811 |
adjust_canvas_dimensions(vr, target, amount) |
| 812 |
struct screen_region *vr; |
| 813 |
struct canvas *target; |
| 814 |
int amount; |
| 815 |
{ /** Modify the size of target by amount. */ |
| 816 |
|
| 817 |
/* Other canvasses in the region will gain or lose |
| 818 |
space to accomodate the change. Return |
| 819 |
the number of rows/columns by which the size |
| 820 |
of target is succesfully enlarged. (if amount <= 0, |
| 821 |
return 0) */ |
| 822 |
|
| 823 |
struct canvas *this; /* for walking the list. */ |
| 824 |
struct canvas *prev; /* for walking the list backwards. */ |
| 825 |
int adjusted; /* Amount already re-allocated. */ |
| 826 |
int *start, *end, *off; /* c->c_{x,y}s, c->c_{x,y}e, and c->c_{x,y}off */ |
| 827 |
int minimum, space; |
| 828 |
|
| 829 |
debug1("adjust: amount = %d\n", amount); |
| 830 |
debug_print_all_canvasses("ADJUST \n"); |
| 831 |
|
| 832 |
ASSERT(vr->count > 1); |
| 833 |
|
| 834 |
if (amount == 0) |
| 835 |
return 0; |
| 836 |
|
| 837 |
switch(vr->type) { |
| 838 |
case HORIZONTAL: minimum = MIN_HEIGHT; space = 2; break; |
| 839 |
case VERTICAL: minimum = MIN_WIDTH; space = 1; break; |
| 840 |
default: ASSERT(0); |
| 841 |
} |
| 842 |
|
| 843 |
if (amount < 0) { |
| 844 |
debug_print_all_canvasses("PREADJUST\n"); |
| 845 |
|
| 846 |
get_endpoints(target, &start, &end, &off); |
| 847 |
if (target == vr -> start) { |
| 848 |
*end += amount; |
| 849 |
|
| 850 |
if (*end < *start + minimum) |
| 851 |
*end = *start + minimum; |
| 852 |
|
| 853 |
get_endpoints(target->c_next, &start, 0, &off); |
| 854 |
*start = *off = *end + space; |
| 855 |
|
| 856 |
debug_print_all_canvasses("POSTADJUST\n\n"); |
| 857 |
} |
| 858 |
else { |
| 859 |
for (prev = vr->start; prev->c_next != target; prev = prev->c_next) |
| 860 |
; |
| 861 |
ASSERT(prev && prev -> c_next == target); |
| 862 |
|
| 863 |
*start -= amount; |
| 864 |
if (*start > *end - minimum) |
| 865 |
*start = *end - minimum; |
| 866 |
get_endpoints(prev, 0, &end, 0); |
| 867 |
*end = *start - space; |
| 868 |
} |
| 869 |
return 0; |
| 870 |
} |
| 871 |
|
| 872 |
ASSERT (amount > 0); |
| 873 |
|
| 874 |
/* Reallocate space from canvasses below target. */ |
| 875 |
this = vr -> end; |
| 876 |
adjusted = 0; |
| 877 |
while ( adjusted < amount) { |
| 878 |
int this_amount; /* amount this canvas can yield. */ |
| 879 |
struct canvas *cv; /* For walking lists. */ |
| 880 |
|
| 881 |
if (this == target) |
| 882 |
break; |
| 883 |
|
| 884 |
get_endpoints(this, &start, &end, 0); |
| 885 |
switch (vr->type) { |
| 886 |
case HORIZONTAL: this_amount = *end - *start - MIN_HEIGHT; break; |
| 887 |
case VERTICAL: this_amount = *end - *start - MIN_WIDTH; break; |
| 888 |
default: ASSERT(0); |
| 889 |
} |
| 890 |
|
| 891 |
if (this_amount > amount - adjusted) |
| 892 |
this_amount = amount - adjusted; |
| 893 |
|
| 894 |
debug("target:\n"); |
| 895 |
debug_print_canvas(target); |
| 896 |
|
| 897 |
debug("this:\n"); |
| 898 |
debug_print_canvas(this); |
| 899 |
|
| 900 |
/* Move all canvasses between target and this by this_amount. */ |
| 901 |
for (cv = target; cv != this; cv = cv -> c_next) { |
| 902 |
debug1("this_amount = %d\n", this_amount); |
| 903 |
debug_print_canvas(cv); |
| 904 |
|
| 905 |
get_endpoints(cv, &start, &end, 0); |
| 906 |
*end += this_amount; |
| 907 |
get_endpoints(cv->c_next, &start, &end, &off); |
| 908 |
*start += this_amount; |
| 909 |
*off = *start; |
| 910 |
} |
| 911 |
adjusted += this_amount; |
| 912 |
debug1("adjusted: %d\n", adjusted); |
| 913 |
|
| 914 |
debug("target:\n"); |
| 915 |
debug_print_canvas(target); |
| 916 |
|
| 917 |
debug("this:\n"); |
| 918 |
debug_print_canvas(this); |
| 919 |
|
| 920 |
|
| 921 |
/* Get the previous canvas. TODO: include back pointers |
| 922 |
in struct canvas(?). */ |
| 923 |
for (prev = vr->start; prev->c_next != this; prev = prev->c_next) |
| 924 |
ASSERT(prev); |
| 925 |
this = prev; |
| 926 |
} |
| 927 |
debug1("adjusted = %d\n", adjusted); |
| 928 |
if (adjusted == amount || target == vr->start) |
| 929 |
return adjusted; |
| 930 |
|
| 931 |
/* Re-allocate space from canvasses above target. */ |
| 932 |
ASSERT(this == target); |
| 933 |
for (prev = vr->start; prev->c_next != this; prev = prev->c_next) |
| 934 |
ASSERT(prev); |
| 935 |
this = prev; |
| 936 |
|
| 937 |
while (adjusted < amount) { |
| 938 |
int this_amount; /* amount this canvas can yield. */ |
| 939 |
struct canvas *cv; /* For walking lists. */ |
| 940 |
|
| 941 |
get_endpoints(this, &start, &end, 0); |
| 942 |
switch (vr->type) { |
| 943 |
case HORIZONTAL: this_amount = *end - *start - MIN_HEIGHT; break; |
| 944 |
case VERTICAL: this_amount = *end - *start - MIN_WIDTH; break; |
| 945 |
default: ASSERT(0); |
| 946 |
} |
| 947 |
|
| 948 |
if (this_amount > amount - adjusted) |
| 949 |
this_amount = amount - adjusted; |
| 950 |
|
| 951 |
/* Move all canvasses between this and target by this_amount. */ |
| 952 |
for (cv = this; cv != target; cv = cv -> c_next) { |
| 953 |
ASSERT(cv); |
| 954 |
debug1("this_amount = %d\n", this_amount); |
| 955 |
debug_print_canvas(cv); |
| 956 |
debug("NEXT:\n"); |
| 957 |
debug_print_canvas(cv->c_next); |
| 958 |
|
| 959 |
debug("getend:\n"); |
| 960 |
get_endpoints(cv, &start, &end, 0); |
| 961 |
ASSERT(end && start ); |
| 962 |
ASSERT(start); |
| 963 |
ASSERT(*end >= this_amount); |
| 964 |
*end -= this_amount; |
| 965 |
ASSERT(*end > *start); |
| 966 |
|
| 967 |
debug("getend:\n"); |
| 968 |
ASSERT(cv->c_next); |
| 969 |
get_endpoints(cv->c_next, &start, &end, &off); |
| 970 |
ASSERT(start && off); |
| 971 |
ASSERT(*start >= this_amount); |
| 972 |
ASSERT(*start == *off); |
| 973 |
*start -= this_amount; |
| 974 |
*off = *start; |
| 975 |
|
| 976 |
debug("adjusted\n"); |
| 977 |
debug_print_canvas(cv); |
| 978 |
debug("NEXT:\n"); |
| 979 |
debug_print_canvas(cv->c_next); |
| 980 |
debug("\n"); |
| 981 |
} |
| 982 |
adjusted += this_amount; |
| 983 |
|
| 984 |
if (this == vr->start) |
| 985 |
break; |
| 986 |
|
| 987 |
for (prev = vr->start; prev->c_next != this; prev = prev->c_next) |
| 988 |
ASSERT(prev); |
| 989 |
this = prev; |
| 990 |
} |
| 991 |
debug1("returning: %d\n", adjusted); |
| 992 |
return adjusted; |
| 993 |
} |
| 994 |
|
| 995 |
void |
| 996 |
equalize_canvas_dimensions(vr) |
| 997 |
struct screen_region *vr; |
| 998 |
{ /** Reset the size of each canvas in the region. */ |
| 999 |
|
| 1000 |
struct canvas *cv; /* for walking the list. */ |
| 1001 |
int this_size; /* new size of cv */ |
| 1002 |
int this_start; /* Start coordinate for current canvas. */ |
| 1003 |
|
| 1004 |
debug("equalize\n"); |
| 1005 |
|
| 1006 |
debug2("vr start = %#x, vr end = %#x\n", vr->start, vr->end); |
| 1007 |
|
| 1008 |
switch(vr->type) { |
| 1009 |
case VERTICAL: this_start = vr->xs; break; |
| 1010 |
case HORIZONTAL: this_start = vr->ys; break; |
| 1011 |
} |
| 1012 |
|
| 1013 |
for (cv = vr->start ; ; cv = cv->c_next) { |
| 1014 |
ASSERT(cv); |
| 1015 |
|
| 1016 |
/* For the horizontal split, leave space for a status line. */ |
| 1017 |
this_size = vr->expanse / vr->count - (vr->type == HORIZONTAL); |
| 1018 |
|
| 1019 |
/* Give any additional available rows/columns to the foreground. */ |
| 1020 |
if (cv == D_forecv) |
| 1021 |
this_size += vr->expanse % vr->count; |
| 1022 |
|
| 1023 |
debug_print_canvas(cv); |
| 1024 |
debug2("cv type = %d, vr type = %d\n", cv->c_type, vr->type); |
| 1025 |
ASSERT(cv -> c_type == vr->type); |
| 1026 |
|
| 1027 |
switch(vr->type) { |
| 1028 |
case VERTICAL: |
| 1029 |
cv -> c_xs = cv -> c_xoff = this_start; |
| 1030 |
cv -> c_xe = this_start + this_size - 1; |
| 1031 |
this_start += this_size; |
| 1032 |
break; |
| 1033 |
case HORIZONTAL: |
| 1034 |
if (cv == vr->end && cv->c_ye == D_height-1- |
| 1035 |
(D_has_hstatus == HSTATUS_LASTLINE)) |
| 1036 |
this_size += 1; /* Don't make space for status line |
| 1037 |
in the bottom region (it already has one). */ |
| 1038 |
|
| 1039 |
cv -> c_ys = cv -> c_yoff = this_start; |
| 1040 |
cv -> c_ye = this_start + this_size - 1; |
| 1041 |
this_start += this_size + 1; /* add one for status line. */ |
| 1042 |
break; |
| 1043 |
} |
| 1044 |
if (cv == vr->end) |
| 1045 |
break; |
| 1046 |
} |
| 1047 |
} |
| 1048 |
|
| 1049 |
void |
| 1050 |
remove_canvas_from_list(list, cv) |
| 1051 |
struct canvas **list; |
| 1052 |
struct canvas *cv; |
| 1053 |
{ /** Prune cv from the list. Does not free cv.*/ |
| 1054 |
|
| 1055 |
struct canvas *pred; /* Predecssor of cv in list. */ |
| 1056 |
|
| 1057 |
if (cv == *list ) { |
| 1058 |
*list = cv -> c_next; |
| 1059 |
} |
| 1060 |
else { |
| 1061 |
/* Find the predecessor of cv. */ |
| 1062 |
for (pred = *list; pred->c_next != cv; pred = pred->c_next) |
| 1063 |
ASSERT(pred); |
| 1064 |
|
| 1065 |
pred -> c_next = cv -> c_next; |
| 1066 |
} |
| 1067 |
} |
| 1068 |
|
| 1069 |
void |
| 1070 |
redirect_pointers(list, old, new) |
| 1071 |
struct canvas *list; |
| 1072 |
struct canvas *old; |
| 1073 |
struct canvas *new; |
| 1074 |
{ /** For each canvas in the list, change any |
| 1075 |
of its screen orientation pointers from old to new. |
| 1076 |
Canvasses are not allowed to be self-referential, |
| 1077 |
so set such pointers to NULL. |
| 1078 |
*/ |
| 1079 |
struct canvas *cv; |
| 1080 |
for (cv=list; cv; cv = cv->c_next) { |
| 1081 |
if (cv -> c_left == old) |
| 1082 |
cv -> c_left = (cv==new)?NULL:new; |
| 1083 |
if (cv -> c_above == old) |
| 1084 |
cv -> c_above = (cv==new)?NULL:new; |
| 1085 |
if (cv -> c_right == old) |
| 1086 |
cv -> c_right = (cv==new)?NULL:new; |
| 1087 |
if (cv -> c_below == old) |
| 1088 |
cv -> c_below = (cv==new)?NULL:new; |
| 1089 |
} |
| 1090 |
} |
| 1091 |
|
| 1092 |
struct canvas * |
| 1093 |
squeeze(list, target, direction, distance) |
| 1094 |
struct canvas *list; /* List of canvasses to resize. */ |
| 1095 |
struct canvas *target; /* Canvas in the list being removed. */ |
| 1096 |
enum directions direction; |
| 1097 |
int distance; /* Amount to squeeze. */ |
| 1098 |
{ /** Resize canvasses in the list so that target |
| 1099 |
is shrunk by distance and other canvasses are grown in the |
| 1100 |
specified direction. If distance is 0, target |
| 1101 |
is destroyed, and the value returned is |
| 1102 |
the earliest canvas in the list that is grown. |
| 1103 |
|
| 1104 |
If distance > 0, the value returned is an int, |
| 1105 |
giving the amount actually sqeezed. (This needs |
| 1106 |
re-writing!) |
| 1107 |
(This becomes the new region head for the region |
| 1108 |
orphaned by target.) |
| 1109 |
|
| 1110 |
TODO: this currently only implements distance == 0; |
| 1111 |
*/ |
| 1112 |
|
| 1113 |
struct canvas *ret; /* The return value.*/ |
| 1114 |
struct canvas *cv; /* For walking the list.*/ |
| 1115 |
|
| 1116 |
ret = NULL; |
| 1117 |
|
| 1118 |
if (distance == 0) { |
| 1119 |
for (cv = list; cv; cv = cv->c_next) { |
| 1120 |
int *cv_coord, *cv_off, targ_coord; |
| 1121 |
struct canvas **cv_orient, *targ_orient; |
| 1122 |
|
| 1123 |
switch (direction) { |
| 1124 |
case RIGHT: |
| 1125 |
cv_orient = &cv->c_right; |
| 1126 |
cv_coord = &cv->c_xe; |
| 1127 |
cv_off = 0; |
| 1128 |
targ_coord = target->c_xe; |
| 1129 |
targ_orient = target->c_right; |
| 1130 |
break; |
| 1131 |
case LEFT: |
| 1132 |
cv_orient = &cv->c_left; |
| 1133 |
cv_coord = &cv->c_xs; |
| 1134 |
cv_off = &cv->c_xoff; |
| 1135 |
targ_coord = target->c_xs; |
| 1136 |
targ_orient = target->c_left; |
| 1137 |
break; |
| 1138 |
case UP: |
| 1139 |
cv_orient = &cv->c_above; |
| 1140 |
cv_coord = &cv->c_ys; |
| 1141 |
cv_off = &cv->c_yoff; |
| 1142 |
targ_coord = target->c_ys; |
| 1143 |
targ_orient = target->c_above; |
| 1144 |
break; |
| 1145 |
case DOWN: |
| 1146 |
cv_orient = &cv->c_below; |
| 1147 |
cv_coord = &cv->c_ye; |
| 1148 |
cv_off = 0; |
| 1149 |
targ_coord = target->c_ye; |
| 1150 |
targ_orient = target->c_below; |
| 1151 |
break; |
| 1152 |
} |
| 1153 |
if (*cv_orient == target) { |
| 1154 |
*cv_coord = targ_coord; |
| 1155 |
if(cv_off) |
| 1156 |
*cv_off = targ_coord; |
| 1157 |
*cv_orient = targ_orient; |
| 1158 |
ret = (ret) ? ret : cv; |
| 1159 |
} |
| 1160 |
} |
| 1161 |
} |
| 1162 |
else { |
| 1163 |
ASSERT(distance > 0); |
| 1164 |
switch (direction) { |
| 1165 |
/* adjust target first. */ |
| 1166 |
case RIGHT: |
| 1167 |
if (target->c_xe - target->c_xs + distance < MIN_WIDTH) |
| 1168 |
distance = target->c_xe - target->c_xs - MIN_WIDTH; |
| 1169 |
target->c_xs += distance; |
| 1170 |
target->c_xoff = target -> c_xs; |
| 1171 |
break; |
| 1172 |
case LEFT: |
| 1173 |
if (target->c_xe - target->c_xs + distance < MIN_WIDTH) |
| 1174 |
distance = target->c_xe - target->c_xs - MIN_WIDTH; |
| 1175 |
target->c_xe -= distance; |
| 1176 |
break; |
| 1177 |
case UP: |
| 1178 |
if (target->c_ye - target->c_ys + distance < MIN_HEIGHT) |
| 1179 |
distance = target->c_ye - target->c_ys - MIN_HEIGHT; |
| 1180 |
target->c_ye -= distance; |
| 1181 |
break; |
| 1182 |
case DOWN: |
| 1183 |
if (target->c_ye - target->c_ys + distance < MIN_HEIGHT) |
| 1184 |
distance = target->c_ye - target->c_ys - MIN_HEIGHT; |
| 1185 |
target->c_ys += distance; |
| 1186 |
target->c_yoff = target -> c_ys; |
| 1187 |
break; |
| 1188 |
} |
| 1189 |
for (cv = list; cv; cv = cv->c_next) { |
| 1190 |
int *cv_coord, *cv_off, new_coord; |
| 1191 |
struct canvas **cv_orient; |
| 1192 |
|
| 1193 |
debug("SQUEEZE\n"); |
| 1194 |
debug_print_canvas(cv); |
| 1195 |
|
| 1196 |
if (cv == target) |
| 1197 |
continue; |
| 1198 |
|
| 1199 |
switch (direction) { |
| 1200 |
case RIGHT: |
| 1201 |
cv_orient = &cv->c_right; |
| 1202 |
cv_coord = &cv->c_xe; |
| 1203 |
cv_off = 0; |
| 1204 |
new_coord = cv->c_xe + distance; |
| 1205 |
break; |
| 1206 |
case LEFT: |
| 1207 |
cv_orient = &cv->c_left; |
| 1208 |
cv_coord = &cv->c_xs; |
| 1209 |
cv_off = &cv->c_xoff; |
| 1210 |
new_coord = cv->c_xs - distance; |
| 1211 |
break; |
| 1212 |
case UP: |
| 1213 |
cv_orient = &cv->c_above; |
| 1214 |
cv_coord = &cv->c_ys; |
| 1215 |
cv_off = &cv->c_yoff; |
| 1216 |
new_coord = cv->c_ys - distance; |
| 1217 |
break; |
| 1218 |
case DOWN: |
| 1219 |
cv_orient = &cv->c_below; |
| 1220 |
cv_coord = &cv->c_ye; |
| 1221 |
cv_off = 0; |
| 1222 |
new_coord = cv->c_ye + distance; |
| 1223 |
break; |
| 1224 |
} |
| 1225 |
if (*cv_orient == target) { |
| 1226 |
*cv_coord = new_coord; |
| 1227 |
if(cv_off) |
| 1228 |
*cv_off = new_coord; |
| 1229 |
} |
| 1230 |
} |
| 1231 |
ret = (struct canvas *) distance; |
| 1232 |
} |
| 1233 |
|
| 1234 |
|
| 1235 |
debug2("squeeze: target = %#x, ret = %#x\n", target, ret); |
| 1236 |
return ret; |
| 1237 |
} |
| 1238 |
|
| 1239 |
|
| 1240 |
struct canvas * |
| 1241 |
grow_surrounding_regions(list, fore, amount) |
| 1242 |
struct canvas *list; |
| 1243 |
struct canvas *fore; |
| 1244 |
int amount; |
| 546 |
{ |
1245 |
{ |
| 547 |
int hh, h, i, j; |
1246 |
/* Grow all the regions in the list that border |
| 548 |
struct canvas *cv, **cvpp; |
1247 |
fore appropriately. */ |
| 549 |
int did = 0; |
1248 |
struct canvas *cv; /* For walking the list. */ |
|
|
1249 |
struct canvas *new_fore; /* Replacement for fore. */ |
| 550 |
|
1250 |
|
| 551 |
h = D_height - (D_has_hstatus == HSTATUS_LASTLINE); |
1251 |
debug("grow_surrounding_regions\n"); |
| 552 |
for (cv = D_cvlist, j = 0; cv; cv = cv->c_next) |
1252 |
|
| 553 |
j++; |
1253 |
new_fore = NULL; |
| 554 |
if (j == 1) |
1254 |
if (amount == 0) { |
| 555 |
return; |
1255 |
if (fore != list) { |
| 556 |
i = 0; |
1256 |
/* Grow the regions from above (the left). */ |
| 557 |
j--; |
1257 |
switch (fore -> c_type) { |
| 558 |
for (cvpp = &D_cvlist; (cv = *cvpp); cvpp = &cv->c_next) |
1258 |
case HORIZONTAL: |
| 559 |
{ |
1259 |
if ( !(new_fore = squeeze(list, fore, DOWN, 0))) |
| 560 |
if (cv == D_forecv && !did) |
1260 |
new_fore = squeeze(list, fore, RIGHT, 0); |
| 561 |
{ |
1261 |
break; |
| 562 |
*cvpp = cv->c_next; |
1262 |
case VERTICAL: |
| 563 |
FreeCanvas(cv); |
1263 |
if ( !(new_fore = squeeze(list, fore, RIGHT, 0))) |
| 564 |
cv = *cvpp; |
1264 |
new_fore = squeeze(list, fore, DOWN, 0); |
| 565 |
D_forecv = cv ? cv : D_cvlist; |
|
|
| 566 |
D_fore = Layer2Window(D_forecv->c_layer); |
| 567 |
flayer = D_forecv->c_layer; |
| 568 |
if (cv == 0) |
| 569 |
break; |
1265 |
break; |
| 570 |
did = 1; |
|
|
| 571 |
} |
1266 |
} |
| 572 |
hh = h / j-- - 1; |
|
|
| 573 |
if (!captionalways && i == 0 && j == 0) |
| 574 |
hh++; |
| 575 |
cv->c_ys = i; |
| 576 |
cv->c_ye = i + hh - 1; |
| 577 |
cv->c_yoff = i; |
| 578 |
i += hh + 1; |
| 579 |
h -= hh + 1; |
| 580 |
} |
1267 |
} |
|
|
1268 |
else { /* Grow the regions from below (the right). */ |
| 1269 |
switch (fore -> c_type) { |
| 1270 |
case HORIZONTAL: |
| 1271 |
if ( !(new_fore = squeeze(list, fore, UP, 0))) |
| 1272 |
new_fore = squeeze(list, fore, LEFT, 0); |
| 1273 |
break; |
| 1274 |
case VERTICAL: |
| 1275 |
if ( !(new_fore = squeeze(list, fore, LEFT, 0))) |
| 1276 |
new_fore = squeeze(list, fore, UP, 0); |
| 1277 |
break; |
| 1278 |
} |
| 1279 |
} |
| 1280 |
ASSERT (new_fore); |
| 1281 |
return new_fore; |
| 1282 |
} |
| 1283 |
} |
| 1284 |
|
| 1285 |
|
| 1286 |
void |
| 1287 |
RemCanvas() |
| 1288 |
{ /** Remove the foreground canvas. */ |
| 1289 |
|
| 1290 |
struct screen_region vr; /*Canvasses in the same row/column as D_forecv.*/ |
| 1291 |
struct canvas *new_fore; /* Canvas which will replace D_forecv. */ |
| 1292 |
|
| 1293 |
/* Do nothing if the foreground is the only canvas. */ |
| 1294 |
if (D_cvlist->c_next == NULL) |
| 1295 |
return; |
| 1296 |
|
| 1297 |
compute_region(D_forecv->c_type, &vr, D_forecv, D_cvlist); |
| 1298 |
|
| 1299 |
debug1("RemCanvas. count = %d\n",vr.count); |
| 1300 |
debug_print_all_canvasses("RemCanvas() start\n"); |
| 1301 |
|
| 1302 |
if (vr.count > 1) { /* Resize the neighboring canvas in region. */ |
| 1303 |
debug2("D_forecv = %x vr.start = %x\n",D_forecv, vr.start); |
| 1304 |
/* If there is a canvas before D_forecv, then |
| 1305 |
grow that canvas to take up the space. */ |
| 1306 |
if (D_forecv != vr.start) { |
| 1307 |
struct canvas *pred; /* Predecssor of D_forecv. */ |
| 1308 |
for (pred = vr.start; pred->c_next != D_forecv; ) |
| 1309 |
pred = pred->c_next; |
| 1310 |
|
| 1311 |
new_fore = pred; |
| 1312 |
new_fore -> c_ye = D_forecv->c_ye; |
| 1313 |
new_fore -> c_xe = D_forecv->c_xe; |
| 1314 |
|
| 1315 |
} |
| 1316 |
else { |
| 1317 |
new_fore = D_forecv -> c_next; |
| 1318 |
new_fore -> c_ys = D_forecv -> c_ys; |
| 1319 |
new_fore -> c_xs = D_forecv -> c_xs; |
| 1320 |
new_fore -> c_yoff = new_fore -> c_ys; |
| 1321 |
new_fore -> c_xoff = new_fore -> c_xs; |
| 1322 |
} |
| 1323 |
} |
| 1324 |
else { /* Resize all bordering regions. */ |
| 1325 |
new_fore = grow_surrounding_regions( D_cvlist, D_forecv,0); |
| 1326 |
} |
| 1327 |
debug_print_canvas(new_fore); |
| 1328 |
|
| 1329 |
/* Redirect all pointers in the list. */ |
| 1330 |
redirect_pointers(D_cvlist, D_forecv, new_fore); |
| 1331 |
|
| 1332 |
remove_canvas_from_list(&D_cvlist, D_forecv); |
| 1333 |
FreeCanvas(D_forecv); |
| 1334 |
D_forecv = new_fore; |
| 1335 |
D_fore = Layer2Window(D_forecv->c_layer); |
| 1336 |
flayer = D_forecv->c_layer; |
| 1337 |
|
| 1338 |
debug2("RemCanvas. forecv = %#x new_fore = %#x\n", D_forecv, new_fore); |
| 1339 |
debug_print_all_canvasses("RemCanvas() end.\n"); |
| 1340 |
|
| 581 |
RethinkDisplayViewports(); |
1341 |
RethinkDisplayViewports(); |
| 582 |
ResizeLayersToCanvases(); |
1342 |
ResizeLayersToCanvases(); |
| 583 |
} |
1343 |
} |
| 584 |
|
1344 |
|
| 585 |
void |
1345 |
void |
| 586 |
OneCanvas() |
1346 |
OneCanvas(list, target) |
| 587 |
{ |
1347 |
struct canvas **list; |
| 588 |
struct canvas *mycv = D_forecv; |
1348 |
struct canvas *target; |
| 589 |
struct canvas *cv, **cvpp; |
1349 |
{ /* Free all canvasses in the list except for |
|
|
1350 |
target. Make *list reference target. */ |
| 1351 |
struct canvas *cv; |
| 1352 |
struct canvas *next; |
| 590 |
|
1353 |
|
| 591 |
for (cvpp = &D_cvlist; (cv = *cvpp);) |
1354 |
debug_print_all_canvasses("OneCanvas start.\n"); |
| 592 |
{ |
1355 |
for (cv = *list; cv; cv = next) { |
| 593 |
if (cv == mycv) |
1356 |
next = cv -> c_next; |
| 594 |
{ |
1357 |
if (cv == target) { |
| 595 |
cv->c_ys = 0; |
1358 |
cv -> c_xoff = 0; |
| 596 |
cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways; |
1359 |
cv -> c_xs = 0; |
| 597 |
cv->c_yoff = 0; |
1360 |
cv -> c_xe = D_width-1; |
| 598 |
cvpp = &cv->c_next; |
1361 |
cv -> c_yoff = 0; |
| 599 |
} |
1362 |
cv -> c_ys = 0; |
| 600 |
else |
1363 |
cv -> c_ye = D_height - 1 - (D_has_hstatus == |
| 601 |
{ |
1364 |
HSTATUS_LASTLINE) - captionalways; |
| 602 |
*cvpp = cv->c_next; |
1365 |
cv -> c_left = cv->c_right = NULL; |
|
|
1366 |
cv -> c_above = cv->c_below = NULL; |
| 1367 |
cv -> c_next = NULL; |
| 1368 |
} else { |
| 603 |
FreeCanvas(cv); |
1369 |
FreeCanvas(cv); |
| 604 |
} |
1370 |
} |
| 605 |
} |
1371 |
} |
|
|
1372 |
*list = target; |
| 1373 |
debug_print_all_canvasses("OneCanvas end.\n"); |
| 1374 |
|
| 606 |
RethinkDisplayViewports(); |
1375 |
RethinkDisplayViewports(); |
| 607 |
ResizeLayersToCanvases(); |
1376 |
ResizeLayersToCanvases(); |
| 608 |
} |
1377 |
} |