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 |
} |