#include #include #include "X10.h" #ifdef SVR4 #include #else #include #endif #include "../sim/CVDefs.h" #include "../data/Parameter.h" /* for get_vardata() */ #include "Xcv.h" extern Display *dpy; extern Window root; extern int screen; extern unsigned long white_pixel, black_pixel; /* Main.c */ extern double getval(); extern XFontStruct *diagram_font; extern XContext circuit_data; extern int addv_next; extern Vertex vlist[]; extern Cursor left_ptr_cursor; extern GC invertGC; extern void mk_icn(), diagram_draw_wires(), diagram_map_icons(); extern XContext assoc_win; extern Window mk_circuit_diagram(); /* from diagram.c */ /*FORWARD*/ void choose_variable(); Window top_w; GC labelGC; static int done; static unsigned long mask; static GC imageGC = 0; int manip_type; /* exported to diagram.c: mk_sys() */ static int *place_ptr, *type_ptr; /*FORWARD*/ static void getWinList(); static Window Diagram = 0; static void hilite(), de_hilite(), goof(); modify_parameters(which, mp_place, mp_type) int which; /* 0: modify independent vars, 1: plot dependent vars,2: plot both*/ int *mp_place, *mp_type; { XEvent event; static winCount = 0; static Window winList[100] = {(Window) 0, }; static Pixmap savedUnder = (Pixmap) 0; XGCValues xgcv; static void handle_ExposeWindow(), handle_EnterWindow(), handle_LeaveWindow(), handle_ButtonPressed(); XWindowAttributes att; int n; if (!Diagram) Diagram = mk_circuit_diagram(100, 100); else XUnmapSubwindows(dpy, Diagram); xgcv.subwindow_mode = IncludeInferiors; if (!imageGC) imageGC = XCreateGC(dpy, root, GCSubwindowMode, &xgcv); if (!labelGC) { xgcv.foreground = white_pixel; xgcv.background = black_pixel; labelGC = XCreateGC(dpy, root, GCForeground | GCBackground, &xgcv); } manip_type = which; place_ptr = mp_place; type_ptr = mp_type; mask = ButtonPressMask | EnterWindowMask | LeaveWindowMask | ExposureMask; top_w = Diagram; XSelectInput(dpy, top_w, mask); /* POP-UP! This does a manual save-under, since I can't get the * automatic one to work. */ #ifndef NOGRABS XGrabServer(dpy); /* Don't let reality change while we've got it saved */ #endif XSync(dpy, False); /* Save the most up-to-date picture possible. */ /* Calculate the footprint of this window. */ XGetWindowAttributes(dpy, top_w, &att); if (!savedUnder) savedUnder = XCreatePixmap(dpy, root, att.width + 2*att.border_width, att.height + 2*att.border_width, DefaultDepth(dpy,screen)); XCopyArea(dpy, root, savedUnder, imageGC, att.x, att.y, att.width+2*att.border_width,att.height+2*att.border_width, 0, 0); XMapRaised(dpy, top_w); if (!winCount) getWinList(top_w, winList, &winCount); done = 0; while(!done) { for (;;) { XMaskEvent(dpy, mask, &event); for (n=0; n < winCount ; n++) if (((XEnterWindowEvent *)&event)->window == winList[n]) goto contin; } contin: switch ((int) event.type) { case Expose: if (((XExposeEvent *)&event)->count == 0) /* Compress multiple rectangle exposure events, using only the last */ handle_ExposeWindow((XExposeEvent *)&event); break; case EnterNotify: handle_EnterWindow((XEnterWindowEvent *)&event); break; case LeaveNotify: handle_LeaveWindow((XLeaveWindowEvent *)&event); break; case ButtonPress: handle_ButtonPressed((XButtonPressedEvent *)&event); break; default: #ifdef DEBUG printf("Not handling event! Type: %d\n", event.type); #endif break; } } /* POP DOWN! */ XUnmapWindow(dpy, Diagram); /* Try to avoid redisplays, since we have saved all the bits. */ XCopyArea(dpy, savedUnder, root, imageGC, 0, 0, att.width + 2*att.border_width, att.height + 2*att.border_width, att.x, att.y); XFreePixmap(dpy, savedUnder); savedUnder = (Pixmap) 0; {/* Discard all accumulated exposure events. */ XEvent ev; XSync(dpy, False); while (XCheckTypedEvent(dpy, Expose, &ev) == True) ; /* discard them since we repainted the screen instead. */ } #ifndef NOGRABS XUngrabServer(dpy); #endif return; } /* This is a recursive, pre-order traversal of all windows with win as * anscestor. The routine builds a list in winList and keeps a count in * countPtr, both returned values. Space for winList & countPtr must be * allocated by calling fn. */ static void getWinList(win, winList, countPtr) Window win; Window *winList; /*RETURN*/ int *countPtr; /*RETURN*/ { unsigned int nchildren; Window *children, parent, root_return; XQueryTree(dpy, win, &root_return, &parent, &children, &nchildren); winList[(*countPtr)++] = win; XSelectInput(dpy, win, mask); while (nchildren--) getWinList(children[nchildren], winList, countPtr); XFree((char *)children); } static void handle_ExposeWindow(e) XExposeEvent *e; { CircInfo *cinfo; Window w; char *label; w = e->window; if (w == top_w) { diagram_map_icons(); diagram_draw_wires(top_w); if (manip_type == 0) label = "Choose Parameter to Modify"; else label = "Choose Variable to Plot"; diagram_draw_label(top_w, label); } else { if (!XFindContext(dpy, w, circuit_data, (caddr_t *)&cinfo)) { if (cinfo && cinfo->mk_fn) (cinfo->mk_fn)(w); XMapSubwindows(dpy, w); } } } Window button = 0; static void handle_ButtonPressed(e) XButtonEvent *e; { Window w, assoc; CircInfo *cinfo; w = e->window; if (w == top_w) { goof(); } else if (w == button) { *place_ptr = *type_ptr = -1; /* Fill return values with null choice */ done = 1; } else { if (!XFindContext(dpy, w, circuit_data, (caddr_t *)&cinfo)) { if (cinfo) switch(cinfo->type) { case IconWindow: if (!XFindContext(dpy, w, assoc_win, (caddr_t *)&assoc)) { XUnmapWindow(dpy, w); XMapRaised(dpy, assoc); } break; case CircuitWindow: case DiodeWindow: goof(); /*noop...or error feep*/ break; default: if (cinfo) choose_variable(cinfo, manip_type); break; } } } } static void handle_EnterWindow(e) XCrossingEvent *e; { Window w = e->window; if (w == top_w) { ; /*noop*/ } else switch (e->detail) { case NotifyAncestor: case NotifyNonlinear: case NotifyNonlinearVirtual: hilite(w); break; case NotifyInferior: /*noop*/ break; } } static void handle_LeaveWindow(e) XCrossingEvent *e; { Window w, icon; CircInfo *cinfo; XWindowAttributes win_attrs; w = e->window; if (w == top_w) { ; /* do nothing */ } else { if (!XFindContext(dpy, w, circuit_data, (caddr_t *)&cinfo)) { if (cinfo && cinfo->type == IconWindow) { XGetWindowAttributes(dpy, w, &win_attrs); if (win_attrs.map_state == IsUnmapped) { /*TAG ... I think we would rather do nothing here. if (!XFindContext(dpy, w, assoc_win, &icon)) { XUnmapWindow(dpy, icon); XMapRaised(dpy, w); } */ ; } else { de_hilite(w); } } else switch (e->detail) { case NotifyNonlinear: case NotifyNonlinearVirtual: case NotifyAncestor: if (cinfo && cinfo->type == CircuitWindow) { if (!XFindContext(dpy, w, assoc_win, (caddr_t *)&icon)) { XUnmapWindow(dpy, w); XMapRaised(dpy, icon); } } else { de_hilite(w); } break; case NotifyInferior: ;/*noop*/ break; } } } } static void hilite(w) Window w; { CircInfo *cinfo; if (!XFindContext(dpy, w, circuit_data, (caddr_t *)&cinfo)) { if (cinfo) switch(cinfo->type) { case IconWindow: if (cinfo->mk_fn) (cinfo->mk_fn)(w); XMapSubwindows(dpy, w); XFillRectangle(dpy, w, invertGC, 0, 0, cinfo->width, cinfo->height); /*TAG printf("Highlight this window! w = 0x%x\n", w); */ break; case ResistorWindow: case CapacitorWindow: case VarCapacitorWindow: /* These are InputOnly windows, so must instead write to parent */ { Window root_ret, parent, *children; unsigned int nchildren; int x, y; XQueryTree(dpy, w, &root_ret, &parent, &children, &nchildren); XFree((char *)children); XTranslateCoordinates(dpy, w, parent, 0, 0, &x, &y, &root_ret); XFillRectangle(dpy, parent,invertGC, x, y, cinfo->width,cinfo->height); break; } case CircuitWindow: case DiodeWindow: /* not hilited */ break; } } } static void de_hilite(w) Window w; { CircInfo *cinfo; hilite(w); if (!XFindContext(dpy, w, circuit_data, (caddr_t *)&cinfo)) { if (cinfo->mk_fn) (cinfo->mk_fn)(w); XMapSubwindows(dpy, w); } } static void goof()/* on error buttonpress etc. */ { /* printf("GOOF!\n"); */ } void choose_variable(cinfo, mode) /* used locally and by diagram.c:mk_sys()*/ CircInfo *cinfo; int mode; { VarData *vd; Window w, w2, button[10], button_done, root_return, child_return; char *str; int i, n, vars[20]; XEvent xevent; XButtonEvent *bevent = (XButtonEvent *) &xevent; int done2, x, y, root_x, root_y; unsigned long mask; unsigned int mask_return; static GC textGC = 0; XGCValues xgcv; static Pixmap savedUnder = (Pixmap) 0; XWindowAttributes att; XSizeHints hints; XSetWindowAttributes attributes; XQueryPointer(dpy, root, &root_return, &child_return, &root_x, &root_y, &x, &y, &mask_return); attributes.override_redirect = True; attributes.background_pixel = white_pixel; attributes.border_pixel = black_pixel; w = XCreateWindow(dpy, root, x, y, 300, 120, 2, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect | CWBorderPixel | CWBackPixel, &attributes); hints.x = x; hints.y = y; hints.width = 300; hints.height = 120; hints.flags = USPosition | USSize; XSetNormalHints(dpy, w, &hints); XSetTransientForHint(dpy, w, Diagram); XDefineCursor(dpy, w, left_ptr_cursor); n=0; if (mode != 0) for (n = 0; cinfo->depvars[n] != ENDVAR; n++) vars[n] = cinfo->depvars[n]; if (mode == 2) vars[n++] = 999; if (mode != 1) for (i = n; cinfo->indepvars[n-i] != ENDVAR; n++) vars[n] = cinfo->indepvars[n-i]; vars[n] = ENDVAR; if (mode == 0) str = "Modification Choices:"; else str = "Plotting Choices:"; n = 0; while (vars[n] != ENDVAR) { if (vars[n] == 999) button[n] = (Window)0; /*space holder*/ else button[n] = XCreateSimpleWindow(dpy,w, 10, 30+15*n, 10, 10, 1, white_pixel, black_pixel); n++; } button_done = XCreateSimpleWindow(dpy,w, 10, 30+15*n++, 10, 10, 1, white_pixel, black_pixel); XResizeWindow(dpy, w, 300, 30+15*n); mask = ButtonPressMask | EnterWindowMask | LeaveWindowMask | ExposureMask; XSelectInput(dpy, w, mask); XMapSubwindows(dpy, w); { /* POP-UP! This does a manual save-under, since I can't get the * automatic one to work. */ XSync(dpy, False); /* Save the most up-to-date picture possible. */ /* Calculate the footprint of this window. */ XGetWindowAttributes(dpy, w, &att); savedUnder = XCreatePixmap(dpy, root, att.width + 2*att.border_width, att.height + 2*att.border_width, DefaultDepth(dpy,screen)); XCopyArea(dpy, root, savedUnder, imageGC, att.x, att.y, att.width+2*att.border_width,att.height+2*att.border_width,0,0); } XMapRaised(dpy, w); done2 = 0; xgcv.font = diagram_font->fid; xgcv.foreground = black_pixel; xgcv.background = white_pixel; if (!textGC) textGC = XCreateGC(dpy, root, GCFont | GCForeground | GCBackground, &xgcv); while(!done2) { XWindowEvent(dpy, w, mask, &xevent); switch ((int) xevent.type) { case Expose: if (((XExposeEvent *)&xevent)->count == 0) { /* Compress multiple rectangle exposure events, using only the last */ XDrawString(dpy, w, textGC, 10, 10, str, strlen(str)); for (n=0; vars[n] != ENDVAR; n++) { if (vars[n] == 999) XDrawString(dpy, w, textGC, 30, 40+15*n, "----------------------------------------", 40); else { vd = get_vardata(cinfo->place, vars[n]); XDrawString(dpy, w, textGC, 30, 40+15*n, vd->name, strlen(vd->name)); } } XDrawString(dpy,w,textGC, 30, 40+15*n, "Continue", strlen("Continue")); } case EnterNotify: break; case LeaveNotify: break; case ButtonPress: w2 = bevent->window; if (bevent->subwindow) w2 = bevent->subwindow; if (w2 == w) break; if (w2 == button_done) {done2 = 1; break;} for (n=0; n<10; n++) if (button[n] == w2) break; /* IF mode == 0, should make a NumberLine instead! */ /*return to set up plot with this variable */ *place_ptr = cinfo->place; *type_ptr = vars[n]; done2 = 1; done = 1; break; } } /* POP DOWN! */ XDestroyWindow(dpy, w); /* Try to avoid redisplays, since we have saved all the bits. */ XCopyArea(dpy, savedUnder, root, imageGC, 0, 0, att.width + 2*att.border_width, att.height + 2*att.border_width, att.x, att.y); XFreePixmap(dpy, savedUnder); savedUnder = (Pixmap) 0; /* calling routine must discard external exposure events. */ return; } diagram_draw_label(w, label) Window w; char *label; { static XFontStruct *largeFont = NULL; Window root_return; int x_return, y_return; unsigned int width_return, height_return, border_return, depth_return; int string_x; XGCValues xgcv; XGetGeometry(dpy, w, &root_return, &x_return, &y_return, &width_return, &height_return, &border_return, &depth_return); if (!largeFont) largeFont = XLoadQueryFont(dpy, LARGE_FONT); if (largeFont) { xgcv.font = largeFont->fid; XChangeGC(dpy, labelGC, GCFont, &xgcv); string_x = width_return/2 - XTextWidth(largeFont, label, strlen(label))/2; } else string_x = width_return/2 - 10; XDrawString(dpy, w, labelGC, string_x, 30, label, strlen(label)); }