/* * xvtools.c: Misc tools for XView-programs * * $Id: xvtools.c,v 1.1 1996/09/26 20:24:55 mb Exp mb $ * * Copyright (c) 1994-96 Martin Buck * Read COPYING for more information * */ #include #include #include #include #include #include #include #include #include #include #include #include "safe_malloc.h" #include "xvtools.h" #define BORDER_DISTANCE 20 struct popen_list_s { FILE *file; pid_t pid; struct popen_list_s *next; }; typedef struct popen_list_s popen_list_t; static popen_list_t *popen_list; void xv_sleep(int sec, int usec) { struct timeval tv; sigset_t mask, oldmask; tv.tv_sec = sec; tv.tv_usec = usec; sigemptyset(&mask); sigaddset(&mask, SIGIO); sigaddset(&mask, SIGALRM); sigprocmask(SIG_BLOCK, &mask, &oldmask); select(0, NULL, NULL, NULL, &tv); sigprocmask(SIG_SETMASK, &oldmask, NULL); } FILE * xv_popen(const char *cmd, const char *mode) { popen_list_t *ptr; int pipe_fd[2], parent_end, child_end; if (!(ptr = malloc(sizeof(popen_list_t)))) { return NULL; } if (pipe(pipe_fd) < 0) { free(ptr); return NULL; } if (mode[0] == 'r') { parent_end = pipe_fd[0]; child_end = pipe_fd[1]; } else { child_end = pipe_fd[0]; parent_end = pipe_fd[1]; } if (!(ptr->file = fdopen(parent_end, mode))) { free(ptr); close(parent_end); close(child_end); return NULL; } if ((ptr->pid = fork()) < 0) { free(ptr); close(parent_end); close(child_end); return NULL; } /* Child process */ if (!ptr->pid) { fclose(ptr->file); dup2(child_end, (mode[0] == 'r' ? STDOUT_FILENO : STDIN_FILENO)); close(child_end); /* Close all open files from previous popen()-calls */ for (ptr = popen_list; ptr; ptr = ptr->next) { fclose(ptr->file); } execl("/bin/sh", "sh", "-c", cmd, (char *)0); _exit(127); } /* Parent process */ close(child_end); /* Link into popen_list */ ptr->next = popen_list; popen_list = ptr; return ptr->file; } int xv_pclose(Notify_client client, FILE *file) { popen_list_t **ptr, *current; pid_t pid = -1; #if 0 int wstat, wresult; #endif /* Find & remove entry for file in popen_list */ ptr = &popen_list; while (*ptr) { if ((*ptr)->file == file) { current = *ptr; *ptr = (*ptr)->next; pid = current->pid; free(current); break; } ptr = &(*ptr)->next; } if (pid < 0 || fclose(file)) { return -1; } #if 1 /* FIXME: I can't believe there's no way to do a blocking wait3 with XView */ notify_set_wait3_func(client, notify_default_wait3, pid); return 0; #else do { wresult = waitpid(pid, &wstat, 0); } while (wresult == -1 && errno == EINTR); if (wresult == -1) { return -1; } else { return wstat; } #endif } static void confirm_destroy(Xv_notice notice, int value, Event *event) { xv_destroy_safe(notice); } /* Print an alert-box containing a single string */ void confirm_notice(Frame parent, int block, const char *msg) { confirm_notice_v(parent, block, msg, (char *)0); } /* Print an alert-box containing multiple strings; arg-list must be NULL-terminated. */ void confirm_notice_v(Frame parent, int block, const char *msg, ...) { Xv_notice notice; char *catmsg, *nextmsg; va_list argp; va_start(argp, msg); catmsg = sstrdup(msg); while ((nextmsg = va_arg(argp, char*))) { catmsg = sstrapp(catmsg, nextmsg); } va_end(argp); notice = (Xv_notice)xv_create(parent, NOTICE, NOTICE_MESSAGE_STRING, catmsg, NULL); if (block) { xv_set(notice, XV_SHOW, TRUE, NULL); xv_destroy_safe(notice); } else { xv_set(notice, NOTICE_BLOCK_THREAD, FALSE, NOTICE_EVENT_PROC, confirm_destroy, XV_SHOW, TRUE, NULL); xv_set(parent, FRAME_BUSY, FALSE, NULL); } free(catmsg); } void center_frame(Frame parent, Frame new_frame) { int x, y, width, height, screen_num; Window dummy, rootid; Display *dpy; width = xv_get(new_frame, XV_WIDTH); height = xv_get(new_frame, XV_HEIGHT); dpy = (Display *)xv_get(parent, XV_DISPLAY); rootid = xv_get((Xv_object)xv_get(parent, XV_ROOT), XV_XID); screen_num = xv_get((Xv_screen)xv_get(parent, XV_SCREEN), SCREEN_NUMBER); XTranslateCoordinates(dpy, (Window)xv_get(parent, XV_XID), rootid, 0, 0, &x, &y, &dummy); x += ((int)xv_get(parent, XV_WIDTH) - width) / 2; y += ((int)xv_get(parent, XV_HEIGHT) - height) / 2; if (x + width + BORDER_DISTANCE > DisplayWidth(dpy, screen_num)) x = DisplayWidth(dpy, screen_num) - width - BORDER_DISTANCE ; if (x < BORDER_DISTANCE) x = BORDER_DISTANCE; if (y + height + BORDER_DISTANCE > DisplayHeight(dpy, screen_num)) y = DisplayHeight(dpy, screen_num) - height - BORDER_DISTANCE; if (y < BORDER_DISTANCE) y = BORDER_DISTANCE; xv_set(new_frame, XV_X, x, XV_Y, y, NULL); } void set_frame_constraints(Frame frame, int wmin, int wmax, int hmin, int hmax, int flags) { int height, width; height = xv_get(frame, XV_HEIGHT); width = xv_get(frame, XV_WIDTH); /* For maximum sizes, 0 means "infinity" */ if (!wmax) wmax = 100000; if (!hmax) hmax = 100000; xv_set(frame, FRAME_MIN_SIZE, (flags & FRC_WSHRINK) ? wmin : width, (flags & FRC_HSHRINK) ? hmin : height, FRAME_MAX_SIZE, (flags & FRC_WGROW) ? wmax : width, (flags & FRC_HGROW) ? hmax : height, NULL); }