📄 gfxsw.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)gfxsw.c 1.1 92/07/30 Copyr 1984 Sun Micro";#endif#endif/* * Copyright (c) 1984 by Sun Microsystems, Inc. *//* * Overview: Implement the abstraction defined in gfxsw.h */#include <sys/types.h>#include <sys/file.h>#include <signal.h>#include <stdio.h>#include <strings.h>#include <pixrect/pixrect.h>#include <pixrect/pr_util.h>#include <pixrect/memvar.h>#include <sunwindow/rect.h>#include <sunwindow/rectlist.h>#include <sunwindow/cms.h>#include <sunwindow/pixwin.h>#include <sunwindow/win_struct.h>#include <sunwindow/win_environ.h>#include <sunwindow/win_screen.h>#include <suntool/tool.h>#include <suntool/gfxsw.h>#include <suntool/gfxswimpl.h>#include "sunwindow/sv_malloc.h"int gfxsw_selected(), gfxsw_handlesigwinch();void gfxsw_catchsigwinch(), gfxsw_catchsigtstp(), gfxsw_catchsigcont();extern int errno;static struct gfxsubwindow *gfxtakeover;struct gfxsubwindow *gfxsw_init(windowfd, argv) int windowfd; char **argv;{ struct gfxsubwindow *gfx; struct gfx_takeover *gt = (struct gfx_takeover *) 0; char *error_msg = NULL; int retained = 0, oldsigmask; struct screen screen; int parentfd = -1; gfx = (struct gfxsubwindow *) (LINT_CAST( sv_calloc(1, sizeof (struct gfxsubwindow)))); /* * Prevent getting a sigwinch until ready for it. */ oldsigmask = sigblock(1 << (SIGWINCH-1)); if (windowfd) /* * Not taking over window. */ gfx->gfx_windowfd = windowfd; else { /* * Taking over another window. */ if (gfxtakeover) { error_msg = "Can't take over two windows in same process"; errno = 0; goto MsgErrorReturn; } gt = (struct gfx_takeover *) (LINT_CAST( sv_calloc(1, sizeof (struct gfx_takeover)))); gt->gt_rootfd = -1; /* * Get framebuffer device name that may have been passed in. * (none will mean default fb). */ (void)win_initscreenfromargv(&screen, argv); if (screen.scr_fbname[0]) { /* * Try to create new screen to run on. */ if (gfxsw_newscreen(gt, &screen)) { (void)fprintf(stderr, "couldn't create a new screen on %s\n", screen.scr_fbname); goto PErrorReturn; } } else { /* * Determine what window to run in. */ if (we_getgfxwindow(gt->gt_parentname) && we_getmywindow(gt->gt_parentname) && we_getparentwindow(gt->gt_parentname) && gfxsw_newscreen(gt, &screen)) { (void)fprintf(stderr, "gfxsw: no %s or %s in environment\n", "WINDOW_GFX", "WINDOW_ME"); error_msg = " Cannot find a frame buffer"; errno = 0; goto MsgErrorReturn; } } /* * Open gt->gt_parentname window */ if ((parentfd = open(gt->gt_parentname, O_RDONLY, 0)) < 0) { (void)fprintf(stderr, "%s would not open\n", gt->gt_parentname); goto PErrorReturn; } /* * Create new window */ if ((gfx->gfx_windowfd = win_getnewwindow()) < 0) { error_msg = "couldn't get a new gfxsw window"; goto MsgErrorReturn; } /* * Setup tool struct for passage to tool_select in gfxsw_select * This is kind of a hack. The tool_select stuff should be * repackaged to accomodate "outside" clients like this. */ gt->gt_tool = (struct tool *) (LINT_CAST( sv_calloc(1, sizeof (struct tool)))); gt->gt_tool->tl_windowfd = gfx->gfx_windowfd; gt->gt_tool->tl_io.tio_handlesigwinch = gfxsw_handlesigwinch; gt->gt_tool->tl_io.tio_selected = gfxsw_selected; } if (argv) { char **args; int nextisreps = 0; /* * Get number of repetitions and retained flag from argv */ gfx->gfx_reps = 200000; for (args = argv;*args;args++) { if (nextisreps) (void) sscanf(*args, "%hd", &gfx->gfx_reps); if (strcmp(*args, "-r") == 0) retained = 1; if (strcmp(*args, "-n") == 0) nextisreps = 1; } } if (gt) { /* * Set up for SIGWINCH signal. */ (void)signal_ifdfl(SIGWINCH, gfxsw_catchsigwinch); /* * Install as blanket window. */ if (win_insertblanket(gfx->gfx_windowfd, parentfd)) { error_msg = "couldn't insert blanket window"; goto MsgErrorReturn; } (void)close(parentfd); /* * Set up for job control signals. * (Doing after insert as blanket because change blanket). */ (void)signal_ifdfl(SIGTSTP, gfxsw_catchsigtstp); (void)signal_ifdfl(SIGCONT, gfxsw_catchsigcont); /* * Set global to notices this situation as takeover one. */ gfxtakeover = gfx; gfx->gfx_takeoverdata = (caddr_t) gt; } (void)win_getsize(gfx->gfx_windowfd, &gfx->gfx_rect); /* * Setup pixwins */#ifdef PRE_IBIS if ((gfx->gfx_pixwin = pw_open(gfx->gfx_windowfd)) ==#else if ((gfx->gfx_pixwin = pw_open_monochrome(gfx->gfx_windowfd)) ==#endif (struct pixwin *)0) goto ErrorReturn; if (retained) (void)gfxsw_getretained(gfx); /* * Now ready for SIGWINCH. */ (void)sigsetmask(oldsigmask); return(gfx);MsgErrorReturn: if (error_msg != NULL) (void)fprintf(stderr, "%s\n", error_msg);PErrorReturn: if (errno != 0) perror("gfxsw");ErrorReturn: if (parentfd != -1) (void)close(parentfd); (void)gfxsw_done(gfx); (void)sigsetmask(oldsigmask); return(0);}gfxsw_newscreen(gt, screen) struct gfx_takeover *gt; struct screen *screen;{ /* * The default kbd and ms should be NONE. */ if (screen->scr_msname[0] == '\0') (void)strncpy(screen->scr_msname, "NONE", SCR_NAMESIZE); if (screen->scr_kbdname[0] == '\0') (void)strncpy(screen->scr_kbdname, "NONE", SCR_NAMESIZE); /* * Create root window */ if ((gt->gt_rootfd = win_screennew(screen)) == -1) { perror("gfxsw"); return(-1); } (void)win_screenget(gt->gt_rootfd, screen); /* * Set up root's name in environment */ (void)win_fdtoname(gt->gt_rootfd, gt->gt_parentname); return(0);}gfxsw_handlesigwinch(gfx) struct gfxsubwindow *gfx;{ struct gfx_takeover *gt = (struct gfx_takeover *) 0; if (gfxtakeover) { /* * In case using this is called with tool handle for gfx */ gfx = gfxtakeover; gt = gfxgettakeover(gfx); gt->gt_tool->tl_flags &= ~TOOL_SIGWINCHPENDING; } /* * Change retained pixrect if size changed. */ if (gfxisretained(gfx) && ((gfx->gfx_rect.r_width != gfx->gfx_pixwin->pw_prretained->pr_width) || (gfx->gfx_rect.r_height != gfx->gfx_pixwin->pw_prretained->pr_height))) { /* * Note: Could copy old to new here but sometimes blows up * with an out of swap space condition. Releasing the old * first reduces the likelyhood of this situation. */ (void)gfxsw_getretained(gfx); } gfx->gfx_flags &= ~GFX_DAMAGED; /* * Toss damaged area if not retained. Fix if retained. */ (void)pw_damaged(gfx->gfx_pixwin); if (gfxisretained(gfx)) (void)pw_repairretained(gfx->gfx_pixwin); (void)pw_donedamaged(gfx->gfx_pixwin); if (gt && gt->gt_selected && (gfx->gfx_flags & GFX_RESTART)) { /* * Give chance to gfxsw_selected to look at GFX_RESTART * so that screen gets fixed before next event actually * happens. */ FD_ZERO(>->gt_tool->tl_io.tio_inputmask); FD_ZERO(>->gt_tool->tl_io.tio_outputmask); FD_ZERO(>->gt_tool->tl_io.tio_exceptmask); (void)gfxsw_selected(gt->gt_tool, >->gt_tool->tl_io.tio_inputmask, >->gt_tool->tl_io.tio_outputmask, >->gt_tool->tl_io.tio_exceptmask, >->gt_tool->tl_io.tio_timer); }}gfxsw_done(gfx) struct gfxsubwindow *gfx;{ if (gfx) { struct gfx_takeover *gt = gfxgettakeover(gfx); /* * Reset state of window */ if (gt) { gfxtakeover = (struct gfxsubwindow *) 0; /* * Gt only non-zero if gt portion of gfxsw_init was * successful. */ (void)resetsignal_todfl(SIGTSTP, gfxsw_catchsigtstp); (void)resetsignal_todfl(SIGCONT, gfxsw_catchsigcont); (void)win_removeblanket(gfx->gfx_windowfd); (void)resetsignal_todfl(SIGWINCH, gfxsw_catchsigwinch); (void)close(gfx->gfx_windowfd); free((char *)(LINT_CAST(gt->gt_tool))); if (gfxmadescreen(gt)) (void)close(gt->gt_rootfd); free((char *)(LINT_CAST(gt))); } if (gfx->gfx_pixwin) (void)pw_close(gfx->gfx_pixwin); free((char *)(LINT_CAST(gfx))); } return;}struct toolsw *gfxsw_createtoolsubwindow(tool, name, width, height, argv) struct tool *tool; char *name; short width, height; char **argv;{ struct toolsw *toolsw; /* * Create subwindow * Note: Should be in another module so doesn't drag in tools code. */ toolsw = tool_createsubwindow(tool, name, width, height); /* * Setup empty subwindow */ if ((toolsw->ts_data = (caddr_t) gfxsw_init(toolsw->ts_windowfd, argv)) == (caddr_t)0) return((struct toolsw *)0); toolsw->ts_io.tio_handlesigwinch = gfxsw_handlesigwinch; toolsw->ts_destroy = gfxsw_done; return(toolsw);}gfxsw_getretained(gfx) struct gfxsubwindow *gfx;{ struct colormapseg cms; (void)pw_getcmsdata(gfx->gfx_pixwin, &cms, (int *)0); if (gfx->gfx_pixwin->pw_prretained) { (void)pr_destroy(gfx->gfx_pixwin->pw_prretained); gfx->gfx_pixwin->pw_prretained = (struct pixrect *)0; } gfx->gfx_pixwin->pw_prretained = mem_create( gfx->gfx_rect.r_width, gfx->gfx_rect.r_height, (cms.cms_size == 2 && gfx->gfx_pixwin->pw_pixrect->pr_depth < 32) ? 1 : gfx->gfx_pixwin->pw_pixrect->pr_depth); if (!gfxisretained(gfx)) (void)fprintf(stderr, "graphics program: can't open retained win\n");}gfxsw_interpretesigwinch(gfx) struct gfxsubwindow *gfx;{ struct rect rect; struct gfx_takeover *gt = gfxgettakeover(gfx); /* * Always restart on size change. */ (void)win_getsize(gfx->gfx_windowfd, &rect); if (!rect_equal(&rect, &gfx->gfx_rect)) { gfx->gfx_flags |= GFX_RESTART; gfx->gfx_rect = rect; } /* * Tell demo to restart after first signal (from win_setowner), * if not retained. */ if (gt) { if (!gfxisretained(gfx)) gfx->gfx_flags |= GFX_RESTART; (void)tool_sigwinch(gt->gt_tool); } else if (!gfxisretained(gfx)) gfx->gfx_flags |= GFX_RESTART; gfx->gfx_flags |= GFX_DAMAGED;}gfxsw_select(gfx, selected, ibits, obits, ebits, timer) struct gfxsubwindow *gfx; int (*selected)(); fd_set ibits, obits, ebits; struct timeval *timer;{ struct gfx_takeover *gt = gfxgettakeover(gfx); gt->gt_selected = selected; gt->gt_tool->tl_io.tio_inputmask = ibits; gt->gt_tool->tl_io.tio_outputmask = obits; gt->gt_tool->tl_io.tio_exceptmask = ebits; gt->gt_tool->tl_io.tio_timer = timer; (void)tool_select(gt->gt_tool, 0); gt->gt_selected = 0;}/*ARGSUSED*/gfxsw_selected(tool, ibitsptr, obitsptr, ebitsptr, timer) struct tool *tool; fd_set *ibitsptr, *obitsptr, *ebitsptr; struct timeval **timer;{ struct gfx_takeover *gt = gfxgettakeover(gfxtakeover); if (gt->gt_selected) gt->gt_selected(gfxtakeover, ibitsptr, obitsptr, ebitsptr, timer);}gfxsw_selectdone(gfx) struct gfxsubwindow *gfx;{ struct gfx_takeover *gt = gfxgettakeover(gfx); (void)tool_done(gt->gt_tool);}voidgfxsw_catchsigwinch(){ if (gfxtakeover == (struct gfxsubwindow *)0) return; (void)gfxsw_interpretesigwinch(gfxtakeover);}voidgfxsw_catchsigtstp(){ struct gfx_takeover *gt; if (gfxtakeover == (struct gfxsubwindow *)0) return; gt = gfxgettakeover(gfxtakeover); /* * Note: Haven't handled case of getting a TSTOP when outside suntools. * For now, do nothing. Could set kbd and ms to NONE and then restore * old values on CONT. */ if (gfxmadescreen(gt)) return; (void)win_removeblanket(gfxtakeover->gfx_windowfd); /* * Reset pixwin while stopped. * Note: Assumes client is using pixwin interface, even when * display is locked, so that pixwin mechanism will notice reset * on the next access. Note, also, that a race condition exists. * If a display access is already in progress then it will complete * after a SIGCONT is sent. */ (void)pw_reset(gfxtakeover->gfx_pixwin); /* * Need to stop self in tracks when get SIGTSTP. */ (void)kill(getpid(), SIGSTOP);}voidgfxsw_catchsigcont(){ struct gfx_takeover *gt; int parentfd; if (gfxtakeover == (struct gfxsubwindow *)0) return; gt = gfxgettakeover(gfxtakeover); /* * Open gt->gt_parentname window */ if ((parentfd = open(gt->gt_parentname, O_RDONLY, 0)) < 0) { (void)fprintf(stderr, "%s would not open\n", gt->gt_parentname); return; } if (win_insertblanket(gfxtakeover->gfx_windowfd, parentfd)) { (void)fprintf(stderr, "couldn't insert blanket window\n"); perror("gfxsw"); } (void)close(parentfd);}signal_ifdfl(sig, catchernew) int sig; void (*catchernew)();{ void (*catcherold)(); struct sigvec vec, ovec;/* if ((catcherold = signal(sig, catchernew)) != SIG_DFL) * (void) signal(sig, catcherold); */ vec.sv_handler = catchernew; vec.sv_mask = vec.sv_onstack = 0; sigvec(sig, &vec, &ovec); if (ovec.sv_handler != SIG_DFL) sigvec(sig, &ovec, 0);}resetsignal_todfl(sig, catchermine) int sig; void (*catchermine)();{ void (*catcherold)(); struct sigvec vec, ovec;/* if ((catcherold = signal(sig, SIG_DFL)) != catchermine) * (void) signal(sig, catcherold); */ vec.sv_handler = SIG_DFL; vec.sv_mask = vec.sv_onstack = 0; sigvec(sig, &vec, &ovec); if (ovec.sv_handler != catchermine) sigvec(sig, &ovec, 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -