2021-10-11 18:37:13 -03:00

251 lines
6.4 KiB
C

#ifndef lint
static char sccsid[] = "@(#)wincms.c 1.1 94/10/31 SMI";
#endif
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
/*
* SunWindows Desktop colormap sharing code.
*/
#include <sunwindowdev/wintree.h>
#include <sys/kmem_alloc.h>
int winenforcecmstd = 1;
void dtop_set_bkgnd();
int
dtop_cmsalloc(dtop, size)
register struct desktop *dtop;
long size;
{
int addr = cms_alloc((struct map *)dtop->dt_rmp, size);
if (addr == 0)
return (-1);
else
return (addr - CRM_ADDROFFSET);
}
dtop_cmsfree(dtop, w)
register struct desktop *dtop;
register struct window *w;
{
struct window *dtop_cmsmatch();
/*
* Releasing color map segment.
*/
if (dtop->dt_cmsize && w->w_cms.cms_size &&
(dtop_cmsmatch(dtop, w, &w->w_cms) == NULL)) {
if (w->w_flags & WF_CMSHOG)
win_freecmapdata(w);
else {
/*
* Guard against the case in which w was allocated,
* a cms segment was assigned, the dtop was closed,
* the w->w_pid was left hung, a new dtop was created,
* w->w_pid was waken to end up on the new dtop,
* w is eventually closed, w's previously assigned
* cms segment (now invalid) is about to be freed
* (which would cause a panic.
*/
if ((dtop->dt_rootwin &&
dtop->dt_rootwin->w_pid <= w->w_pid))
rmfree((struct map *)dtop->dt_rmp,
(long)w->w_cms.cms_size,
(u_long)(w->w_cms.cms_addr + CRM_ADDROFFSET));
/* Reset addr 0 because special for fullscreen access */
if (w->w_cms.cms_addr == 0) {
dtop_set_bkgnd(dtop);
}
}
}
w->w_flags &= ~WF_CMSHOG;
bzero((caddr_t)&w->w_cms, sizeof (struct colormapseg));
bzero((caddr_t)&w->w_cmap, sizeof (struct cms_map));
w->w_cmapdata = 0;
}
struct window *
dtop_cmsmatch(dtop, w, cms)
struct desktop *dtop;
struct window *w;
struct colormapseg *cms;
{
register int wi;
register struct window *wtmp;
/*
* Must search all open windows instead of enumerating dtop because
* need to match cms's whose windows are not in the tree currently.
*/
for (wi = 0; wi != win_nwindows; wi++) {
wtmp = winbufs[wi];
if (wtmp != NULL && wtmp != w &&
(wtmp->w_flags & WF_OPEN) &&
wtmp->w_desktop == dtop &&
strncmp(cms->cms_name, wtmp->w_cms.cms_name,
CMS_NAMESIZE) == 0)
return (wtmp);
}
return (NULL);
}
caddr_t
dtop_alloccmapdata(dtop, cmap, size)
struct desktop *dtop;
register struct cms_map *cmap;
int size;
{
caddr_t cmapdata = new_kmem_zalloc((u_int)3*size, KMEM_SLEEP);
if (cmapdata == 0) {
printf("Couldn't allocate colormap buffer\n");
cms_freecmapdata(cmapdata, cmap, size);
} else {
cmap->cm_red = (u_char *)cmapdata;
cmap->cm_green = cmap->cm_red + size;
cmap->cm_blue = cmap->cm_green + size;
dtop_stdizecmap(dtop, cmap, 0, size);
}
return (cmapdata);
}
dtop_stdizecmap(dtop, cmap, addr, size)
register struct desktop *dtop;
register struct cms_map *cmap;
int addr, size;
{
register struct singlecolor *bkgnd = &dtop->dt_screen.scr_background;
register struct singlecolor *frgnd = &dtop->dt_screen.scr_foreground;
struct singlecolor *tmpgnd;
register int fgnd_index = addr + size - 1, bgnd_index = addr;
/*
* Standardize colormap by setting the foreground and background
* only if they are the same. This is meant to reduce disasterous
* blanking of the screen by errant programs.
*/
if (winenforcecmstd && (size > 0) &&
cmap->cm_red[bgnd_index] == cmap->cm_red[fgnd_index] &&
cmap->cm_green[bgnd_index] == cmap->cm_green[fgnd_index] &&
cmap->cm_blue[bgnd_index] == cmap->cm_blue[fgnd_index]) {
/*
* Use foreground and background from dtop.
* These were made sure to be different in user process
* that called WIN_SCREENNEW (see sunwindow/win_screen.c).
*/
if (dtop->dt_screen.scr_flags & SCR_SWITCHBKGRDFRGRD) {
tmpgnd = bkgnd;
bkgnd = frgnd;
frgnd = tmpgnd;
}
cmap->cm_red[bgnd_index] = bkgnd->red;
cmap->cm_green[bgnd_index] = bkgnd->green;
cmap->cm_blue[bgnd_index] = bkgnd->blue;
cmap->cm_red[fgnd_index] = frgnd->red;
cmap->cm_green[fgnd_index] = frgnd->green;
cmap->cm_blue[fgnd_index] = frgnd->blue;
}
}
/*
* Colormap specific routines
*/
cms_freecmapdata(cmapdata, cmap, size)
register caddr_t cmapdata;
register struct cms_map *cmap;
int size;
{
cmap->cm_red = 0;
cmap->cm_green = 0;
cmap->cm_blue = 0;
if (cmapdata == 0)
return;
kmem_free((caddr_t)cmapdata, (u_int)3*size);
}
int
cms_alloc(rmp, size)
struct map *rmp;
long size;
{
register struct mapent *ep = (struct mapent *)(rmp + 1);
register struct mapent *bp;
register int expo, addr, addrlastok = -1;
/*
* If size is not power of 2 then need to alloc at addr == 0.
*/
for (expo = 1; expo <= 8 /* 2**8==256 */; ++expo) {
if (size == (1 << expo)) {
/*
* Addr % size must be zero.
* Try to allocate from end of space in order to leave
* room at addr == 0 for large consumers.
*/
for (bp = ep; bp->m_size; bp++) {
addr = (bp->m_addr - CRM_ADDROFFSET) +
bp->m_size - size;
addr -= addr % size;
if (addr >= (bp->m_addr - CRM_ADDROFFSET) &&
addr % size == 0)
addrlastok = addr;
}
if (addrlastok != -1)
return (rmget(rmp, size,
(u_long)(addrlastok + CRM_ADDROFFSET)));
else
return (0);
}
}
return (rmget(rmp, size, (u_long)(0 + CRM_ADDROFFSET)));
}
void
dtop_set_bkgnd(dtop)
register Desktop *dtop;
{
register struct singlecolor *bkgnd;
if (dtop->dt_screen.scr_flags & SCR_SWITCHBKGRDFRGRD)
bkgnd = &dtop->dt_screen.scr_foreground;
else
bkgnd = &dtop->dt_screen.scr_background;
dtop->dt_cmap.cm_red[0] = bkgnd->red;
dtop->dt_cmap.cm_green[0] = bkgnd->green;
dtop->dt_cmap.cm_blue[0] = bkgnd->blue;
}
void
dtop_save_grnds(dtop)
register Desktop *dtop;
{
int fg = dtop->dt_cmsize - 1;
dtop->dt_bkgnd_cache.red = dtop->dt_cmap.cm_red[0];
dtop->dt_bkgnd_cache.green = dtop->dt_cmap.cm_green[0];
dtop->dt_bkgnd_cache.blue = dtop->dt_cmap.cm_blue[0];
dtop->dt_frgnd_cache.red = dtop->dt_cmap.cm_red[fg];
dtop->dt_frgnd_cache.green = dtop->dt_cmap.cm_green[fg];
dtop->dt_frgnd_cache.blue = dtop->dt_cmap.cm_blue[fg];
}
void
dtop_restore_grnds(dtop)
register Desktop *dtop;
{
int fg = dtop->dt_cmsize - 1;
dtop->dt_cmap.cm_red[0] = dtop->dt_bkgnd_cache.red;
dtop->dt_cmap.cm_green[0] = dtop->dt_bkgnd_cache.green;
dtop->dt_cmap.cm_blue[0] = dtop->dt_bkgnd_cache.blue;
dtop->dt_cmap.cm_red[fg] = dtop->dt_frgnd_cache.red;
dtop->dt_cmap.cm_green[fg] = dtop->dt_frgnd_cache.green;
dtop->dt_cmap.cm_blue[fg] = dtop->dt_frgnd_cache.blue;
}