Files
Arquivotheca.SunOS-4.1.4/usr.lib/libsunwindow/pw/pw_copy.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

304 lines
8.0 KiB
C

#ifndef lint
#ifdef sccs
static char sccsid[] = "@(#)pw_copy.c 1.1 94/10/31 Copyr 1985 Sun Micro";
#endif
#endif
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
/*
* Pw_copy.c: Implement the pw_copy functions of the pixwin.h interface.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <pixrect/pixrect.h>
#include <pixrect/memvar.h>
#include <pixrect/pr_planegroups.h>
#include <sunwindow/rect.h>
#include <sunwindow/rectlist.h>
#include <sunwindow/cms.h>
#include <sunwindow/pixwin.h>
#include <sunwindow/pw_util.h>
#include <sunwindow/win_screen.h>
#include <sunwindow/win_input.h>
#include <sunwindow/win_ioctl.h>
/*ARGSUSED*/
pwo_copy(pw, xd, yd, width, height, op, pws, xs, ys)
register struct pixwin *pw;
struct pixwin *pws/*Ignored*/;
int op, width, height;
register int xd, yd, xs, ys;
{
struct rect raccess, rsrc;
short left, top;
int planes;
struct colormapseg cms;
int ignore_planes = 0;
struct rectlist rl;
(void)rl_free(&pw->pw_fixup);
if (pw->pw_prretained) {
(void)pr_rop(pw->pw_prretained,
PW_RETAIN_X_OFFSET(pw, xd), PW_RETAIN_Y_OFFSET(pw, yd),
width, height, op, pw->pw_prretained,
PW_RETAIN_X_OFFSET(pw, xs), PW_RETAIN_Y_OFFSET(pw, ys));
rect_construct(&raccess, xd, yd, width, height);
if (pw->pw_clipdata->pwcd_batch_type == PW_NONE)
(void)pw_repair(pw, &raccess);
else
(void)pw_update_batch(pw, &raccess);
return;
} else if (xs != xd && ys != yd) {
/* Diagonal copy of non-retained pixwin using pw_read() */
struct pixrect *pr;
struct rect r;
struct rectlist rlprime;
struct rectnode *rn;
/* Copy source pixwin into a new memory pixrect */
pr = mem_create(width, height, pw->pw_pixrect->pr_depth);
pw_read(pr, 0, 0, width, height, PIX_SRC, pw, xs, ys);
if (rl_equal(&pw->pw_fixup, &rl_null) || pw->pw_clipdata->pwcd_damagedid) {
/* Null fixup list means nothing is unaccessible or
* else damage events caused pw_read to punt and
* and set the fixup list to the source rectangle.
*/
pw_write(pw, xd, yd, width, height, op, pr, 0, 0);
} else {
/* Determine what can be accessed from fixup list */
rect_construct(&r, xs, ys, width, height);
rl = rl_null;
rlprime = rl_null;
rl_initwithrect(&r, &rlprime);
/* rl is the source rect minus the fixup list */
rl_difference(&rlprime, &pw->pw_fixup, &rl);
/* Copy the accessible rectangles */
if (!rl_equal(&rl, &rl_null))
for (rn = rl.rl_head; rn; rn = rn->rn_next) {
int xRelSrc, yRelSrc;
xRelSrc = rn->rn_rect.r_left - xs;
yRelSrc = rn->rn_rect.r_top - ys;
pw_write(pw, xd + xRelSrc, yd + yRelSrc,
rn->rn_rect.r_width, rn->rn_rect.r_height,
op,
pr, xRelSrc, yRelSrc);
}
rl_free(&rl);
rl_free(&rlprime);
}
pr_destroy(pr);
return;
}
/*
* Standard pixrect access setup
*/
left = min(xd, xs);
top = min(yd, ys);
PW_SETUP(pw, raccess, No_op, left, top,
width+(max(xd, xs)-left), height+(max(yd, ys)-top));
/*
* Additional "standard" setup
* Make rest of destination data pixrect relative
*/
rect_construct(&rsrc, xs, ys, width, height);
/* Optimize 8 bit copy */
if (pw->pw_clipdata->pwcd_prmulti->pr_depth == 8) {
int fullplanes = PIX_ALL_PLANES;
(void)pw_getcmsdata(pw, &cms, &planes);
if (cms.cms_size == 2) {
struct winclip winclip;
/* Don't ignore planes if there is damage */
rl = rl_null;
win_getwinclip(pw->pw_windowfd, 1, &winclip, &rl);
if (rl_empty(&rl)) {
(void)pr_putattributes(pw->pw_clipdata->pwcd_prmulti,
&fullplanes);
ignore_planes = 1;
} else
(void)rl_free(&rl);
}
}
if (xs!=xd)
_pw_copyhorizontal(pw, xs, xd, &pw->pw_fixup, &rsrc, op);
if (ys!=yd)
_pw_copyvertical(pw, ys, yd, &pw->pw_fixup, &rsrc, op);
/* Undo optimization of 8 bit copy */
if (ignore_planes)
(void)pr_putattributes(pw->pw_clipdata->pwcd_prmulti, &planes);
/*
* Normalize fixup cause _pw_copy* changed offsets
*/
(void)rl_normalize(&pw->pw_fixup);
/*
* The intersection of rsrc (now equal to the destination) and the
* list of rectangles that couldn't be moved will give another list
* of rectangles that need to be refreshed.
*/
(void)rl_rectintersection(&rsrc, &pw->pw_fixup, &pw->pw_fixup);
/*
* Further reduce the list to be refreshed by intersecting it with
* the exposed portions of the window.
*/
(void)rl_intersection(&pw->pw_fixup, &pw->pw_clipdata->pwcd_clipping,
&pw->pw_fixup);
/*
* Make data in pixwin window relative again
*/
(void)pw_unlock(pw);
/*
* Copy depends on original screen image being correct.
* Otherwise, copy will move around garbage bits that haven't been
* repaired yet. Most user programs wouldn't detect this.
* There is no convenient way to update a current damaged list
* (different from fixup list) with the knowledge of the copy.
* If the damagedid in not 0 then we
* simply make the fixup list all of the bits moved.
*/
if (pw->pw_clipdata->pwcd_damagedid) {
(void)rl_free(&pw->pw_fixup);
(void)rl_initwithrect(&rsrc, &pw->pw_fixup);
}
No_op: /* Change fix up to client coordinate space */
PW_FIXUP_TRANSLATE(pw);
return;
}
_pw_copyvertical(pw, ys, yd, rl_fixup, rsrc, op)
register struct pixwin *pw;
register int ys, yd;
struct rectlist *rl_fixup;
struct rect *rsrc;
int op;
{
struct rectlist rl_saved;
/*
* Make pw->pw_clipping a sorted list and initialize rl_fixup
*/
if (ys < yd)
(void)_pw_sortedrl(pw, RECTS_BOTTOMTOTOP, &rl_saved);
if (ys > yd)
(void)_pw_sortedrl(pw, RECTS_TOPTOBOTTOM, &rl_saved);
if (rl_equal(rl_fixup, &rl_null))
pw_initfixup(pw, rl_fixup);
/*
* Copy data
*/
_pw_copyloop(pw, rsrc, 0, ys-yd, op);
/*
* Reflect new position of bits in source
*/
rsrc->r_top -= ys-yd;
/*
* Shift description of those bits that couldn't move.
*/
rl_fixup->rl_y -= ys-yd;
/*
* Restore original clipping
*/
pw->pw_clipdata->pwcd_clipping = rl_saved;
}
_pw_copyhorizontal(pw, xs, xd, rl_fixup, rsrc, op)
register struct pixwin *pw;
register int xs, xd;
struct rectlist *rl_fixup;
struct rect *rsrc;
int op;
{
struct rectlist rl_saved;
/*
* Make pw->pw_clipping a sorted list and initialize rl_fixup
*/
if (xs < xd)
(void)_pw_sortedrl(pw, RECTS_RIGHTTOLEFT, &rl_saved);
if (xs > xd)
(void)_pw_sortedrl(pw, RECTS_LEFTTORIGHT, &rl_saved);
pw_initfixup(pw, rl_fixup);
/*
* Copy data
*/
_pw_copyloop(pw, rsrc, xs-xd, 0, op);
/*
* Reflect new position of bits in source
*/
rsrc->r_left -= xs-xd;
/*
* Shift description of those bits that couldn't move.
*/
rl_fixup->rl_x -= xs-xd;
/*
* Restore original clipping
*/
pw->pw_clipdata->pwcd_clipping = rl_saved;
}
_pw_copyloop(pw, rsrc, deltax, deltay, op)
register struct pixwin *pw;
register struct rect *rsrc;
short deltax, deltay;
int op;
{
struct rect rsrcinter, rdst, rdstinter;
/*
* Loop on clipping to determine what src you can move.
*/
pw_begincliploop(pw, rsrc, &rsrcinter);
rdst = rsrcinter;
rdst.r_left -= deltax;
rdst.r_top -= deltay;
/*
* Loop on clipping to determine what dest you can move into.
*/
pw_begincliploop2(pw, &rdst, &rdstinter);
/*
* Copy src to dst.
*/
(void)pr_rop(pw->pw_clipdata->pwcd_prmulti,
rdstinter.r_left, rdstinter.r_top,
rdstinter.r_width, rdstinter.r_height,
op, pw->pw_clipdata->pwcd_prmulti,
rsrcinter.r_left+(rdstinter.r_left-rdst.r_left),
rsrcinter.r_top+(rdstinter.r_top-rdst.r_top));
pw_endcliploop();
pw_endcliploop();
return;
}
_pw_sortedrl(pw, direction, rl_saved)
register struct pixwin *pw;
int direction;
struct rectlist *rl_saved;
{
/*
* create pw_pw_clippingsorted[direction] if doesn't exist
*/
if (rl_empty(&pw->pw_clipdata->pwcd_clippingsorted[direction]))
(void)rl_sort(&pw->pw_clipdata->pwcd_clipping,
&pw->pw_clipdata->pwcd_clippingsorted[direction],
direction);
/*
* Save original clipping and make sorted clipping the current clipping
*/
*rl_saved = pw->pw_clipdata->pwcd_clipping;
pw->pw_clipdata->pwcd_clipping =
pw->pw_clipdata->pwcd_clippingsorted[direction];
return(direction);
}