/* $Id: IO.c,v 10.1 92/10/06 22:58:07 ca Exp $ */ #include #include #include #include "sim.h" #include "simx.h" #include "log.h" #include "xtables.h" #include "packet.h" #include "controls.h" #include "peer.h" #include "meters.h" #include "eventdefs.h" #define CLOCK_WIDTH 120 io() { XEvent event, dummy_event; XButtonPressedEvent *bevent; XPointerMovedEvent *bdummy_event; XButtonReleasedEvent *temp_event; XConfigureEvent *revent; XResizeRequestEvent *rrevent; XUnmapEvent *unmapevent; XMapEvent *mapevent; XCOMPONENT *xcomponent; METER *meter; int control_code; int stepped = FALSE; int x,y; int c_m_r = 0; /* 1 if user is doing a click-move-release */ do { /* Add test for single step so that the simulator does not busy wait when single stepping (or before it has started). */ while ((the_environment.single_step && !stepped) || the_environment.never_ran || XPending(the_environment.the_display) != 0) { XNextEvent(the_environment.the_display, &event); if (event.type == Expose || event.type == GraphicsExpose) { general_expose_event_handler((XExposeEvent *) &event); } else if (event.type == ButtonPress) { bevent = (XButtonPressedEvent *) &event; /* Now see what the next event is. It is either a mouse moved or a release button. If it is a mouse moved event, then if the user has moved enough, the user is doing a click-move-release. If it is a release, the user is doing a click-release. Loop until we get one or the other */ for(;;) { XNextEvent(the_environment.the_display, &dummy_event); if (dummy_event.type == MotionNotify) { bdummy_event = (XPointerMovedEvent *) &dummy_event; if ((abs(bdummy_event->x - bevent->x) > the_environment.delta) || (abs(bdummy_event->y - bevent->y) > the_environment.delta)) { c_m_r = 1; break; } else { continue; } } else if (dummy_event.type == ButtonRelease) { temp_event = (XButtonReleasedEvent *) &dummy_event; if (temp_event->button == bevent->button) { c_m_r = 0; break; } else { continue; } } } if ((bevent->button == user_bindings.connection.button) && (bevent->state == user_bindings.connection.key) && (c_m_r == 0)) { neighbor_event_handler(bevent); continue; } else if ((bevent->button == user_bindings.peer.button) && (bevent->state == user_bindings.peer.key) && (c_m_r == 0)) { make_peer_event_handler(bevent); continue; } else if ((bevent->button == user_bindings.create.button) &&(bevent->state == user_bindings.create.key) && (c_m_r == 0) && (bevent->subwindow == 0)) { create_component(bevent->x, bevent->y, NULL); continue; } else if ((bevent->button == user_bindings.create.button) && (bevent->state == user_bindings.create.key) && (c_m_r == 1) && (bevent->subwindow == 0)) { x = bevent->x; y = bevent->y; move_window(&x, &y, the_environment.component_window_width, the_environment.component_window_height, 0, 0); create_component(x, y, NULL); } else if (bevent->subwindow == 0) { continue; } else if ((bevent->button == user_bindings.raise.button) && (bevent->state == user_bindings.raise.key) && (c_m_r == 0)) { XRaiseWindow(the_environment.the_display, bevent->subwindow); continue; } else if ((bevent->button == user_bindings.lower.button) && (bevent->state == user_bindings.lower.key) && (c_m_r == 0)) { XLowerWindow(the_environment.the_display, bevent->subwindow); continue; } else if ((bevent->subwindow == the_environment.clock_window) && (bevent->button == user_bindings.select.button) && (bevent->state == user_bindings.select.key)) { stepped = TRUE; } else if ((bevent->subwindow == the_environment.clock_window) && (bevent->button == user_bindings.move.button) && (bevent->state == user_bindings.move.key) && (c_m_r == 1)) { control_button_press_handler(bevent, 1, c_m_r); } else if (XFindContext(the_environment.the_display, bevent->subwindow, meter_xtable, (caddr_t *) &meter) == 0) { meter_button_event_handler(meter, bevent, c_m_r); continue; } /* He has chosen a component or info window. Set xcomponent to be a pointer to the window's XCOMPONENT structure.*/ else if (XFindContext(the_environment.the_display, bevent->subwindow, comp_xtable, (caddr_t *) &xcomponent) == 0) switch(xcomponent->which_one) { /* User has clicked on component window */ case (COMP_WINDOW): component_button_event_handler(xcomponent, bevent, c_m_r); break; /* User has clicked on an info window */ case (INFO_WINDOW): infowindow_button_event_handler(xcomponent, bevent, c_m_r); break; default: break; } else if (XFindContext(the_environment.the_display, bevent->subwindow, meterinfo_xtable, (caddr_t *) &meter) == 0) { meter_info_window_button_event_handler(meter, bevent, c_m_r); continue; } else if (XFindContext(the_environment.the_display, bevent->subwindow, control_xtable, (caddr_t *) &control_code) == 0) { control_button_press_handler(bevent, control_code, c_m_r); } } else if (event.type == UnmapNotify) { unmapevent = (XUnmapEvent *) &event; if (unmapevent->window == the_environment.back_window) the_environment.iconified = TRUE; } else if (event.type == MapNotify) { mapevent = (XMapEvent *)&event; if (mapevent->window == the_environment.back_window) the_environment.iconified = FALSE; } else if (event.type == ConfigureNotify) { revent = (XConfigureEvent *) &event; if (revent->window == the_environment.back_window) { the_environment.width = revent->width; the_environment.height = revent->height; the_environment.x_center = the_environment.width /2; the_environment.y_center = the_environment.height /2; move_text_window(revent->height); move_controls_to_top_right(); } } } } while (the_environment.single_step && !stepped); XFlush(the_environment.the_display); } /* This routine accepts a pointer to an expose event and handles it. It can refresh components, infowindows, control windows, the clock, meters, and the background. */ general_expose_event_handler(xevent) XExposeEvent *xevent; { XCOMPONENT *xcomponent; METER *meter; int control; /* if (xevent->count != 0) return; */ if (xevent->type == Expose) { if (xevent->count == 0 && xevent->window == the_environment.back_window) { connect_components(); } else if (xevent->count == 0 && xevent->window == the_environment.icon_window) draw_icon_clock((tick_t) TICKS_TO_USECS(ev_now()/1000)); else if (xevent->count == 0 && xevent->window == the_environment.clock_window) paint_clock(); else if (XFindContext(the_environment.the_display, xevent->window, comp_xtable, (caddr_t *) &xcomponent) == 0) { if (xcomponent->which_one == INFO_WINDOW) paint_info_window(xcomponent->scomponent, xcomponent, xevent); else if (xevent->count == 0) paint_comp_window(xcomponent->scomponent, xcomponent); } else if (XFindContext(the_environment.the_display, xevent->window, meter_xtable, (caddr_t *) &meter) == 0) paint_meter(meter->scomponent, meter->parameter, meter, xevent); else if (xevent->count > 0) return; /* No expose for later ones til count == 0 */ else if (XFindContext(the_environment.the_display, xevent->window, meterinfo_xtable, (caddr_t *) &meter) == 0) paint_meter_info_window(meter); else if (XFindContext(the_environment.the_display, xevent->window, control_xtable, (caddr_t *) &control) == 0) paint_controls(control); } else { if (XFindContext(the_environment.the_display, xevent->window, meter_xtable, (caddr_t *) &meter) == 0) paint_meter(meter->scomponent, meter->parameter, meter, xevent); } } toggle_logging(xcomponent, position) XCOMPONENT *xcomponent; int position; { PARAM *parameter; int y; parameter = xcomponent->p_list[position]; if ( ! (parameter->p_flags & CanHaveLogMask)) return; if (parameter->p_flags & LogMask) { log_param_close(parameter); parameter->p_flags &= ~LogMask; /* paint_info_window(xcomponent->scomponent, xcomponent, NULL);*/ } else if (log_param_create(xcomponent->scomponent, parameter) == TRUE) { parameter->p_flags |= LogMask; /* paint_info_window(xcomponent->scomponent, xcomponent, NULL);*/ } y = position * the_environment.info_window_height; XFillRectangle(the_environment.the_display, xcomponent->info_window, (parameter->p_flags & LogMask ? the_environment.meter_or_log_indicator_gc : xcomponent->back_gc), the_environment.meter_indicator_width, (y > 0 ? y+1 : 0), the_environment.meter_indicator_width, the_environment.info_window_height - (y > 0 ? 1 : 0)); } XCOMPONENT *get_xcomponent() { XCOMPONENT *xcomponent; XEvent event; XButtonPressedEvent *bevent; int control; for (;;) { XNextEvent(the_environment.the_display, &event); if (event.type == ButtonPress) { bevent = (XButtonPressedEvent *) &event; if (XFindContext(the_environment.the_display, bevent->subwindow, control_xtable, (caddr_t *) &control) == 0) { if (control == QUIT) return (NULL); } if (XFindContext(the_environment.the_display, bevent->subwindow, comp_xtable, (caddr_t *) &xcomponent) != 0) continue; if (xcomponent->which_one != COMP_WINDOW) continue; return(xcomponent); } else if (event.type == Expose) { general_expose_event_handler((XExposeEvent *) &event); } } } /* This routine destroys everything so that a new congiguration can be loaded. */ destroy_world() { COMPONENT *scomponent; COMPONENT *dummy_variable; for (scomponent = (COMPONENT *)comps->l_head; scomponent != NULL; scomponent = dummy_variable->co_next) { unpop_comp_window(scomponent); dummy_variable = (COMPONENT *) scomponent; (*scomponent->co_action) (NULL, scomponent, EV_DEL, NULL, NULL); } free((char *)comps); ev_reset(); pk_free_all(); /********************** do peer staff written at UMCP ************************/ peer_destroy(); peer_create(); XClearWindow(the_environment.the_display, the_environment.back_window); XFlush(the_environment.the_display); } /* This routine resets all of the X stuff (meters). */ x_reset() { int counter; COMPONENT *scomponent; TH *time_history; PARAM *parameter; METER *meter; XCOMPONENT *xcomponent; for (scomponent = (COMPONENT *) comps->l_head; scomponent != NULL; scomponent = scomponent->co_next) { xcomponent = (XCOMPONENT *) scomponent->co_picture; for (counter = 0; counter != xcomponent->num_meters; ++counter) { parameter = xcomponent->m_list[counter]; meter = (METER *) parameter->p_my_picture; time_history = (TH *) meter->th; if (time_history != NULL) time_history->time = 0; } } paint_clock(); } move_window(xi,yi, width, height, xoffset, yoffset) int width, height; /* dimensions of window that will be moved */ /* use these dimensions as those of flashing window */ int *xi, *yi; /* These will initially contain the x,y of the window */ /* program will set them equal to the new x,y values. */ int xoffset, yoffset; { int x,y; int nx, ny; XEvent event; XButtonReleasedEvent *bevent; XPointerMovedEvent *mevent; x = (int) *xi - xoffset; y = (int) *yi - yoffset; XDrawRectangle(the_environment.the_display, the_environment.back_window, the_environment.xor_gc, x,y, width, height); XFlush(the_environment.the_display); for(;;) { XNextEvent(the_environment.the_display, &event); if (event.type == ButtonRelease) { bevent = (XButtonReleasedEvent *) &event; if (bevent->button == user_bindings.move.button) break; } else if (event.type == MotionNotify) { mevent = (XPointerMovedEvent *) &event; nx = mevent->x - xoffset; ny = mevent->y - yoffset; } XDrawRectangle(the_environment.the_display, the_environment.back_window, the_environment.xor_gc, x,y, width, height); x = nx; y = ny; XDrawRectangle(the_environment.the_display, the_environment.back_window, the_environment.xor_gc, x,y, width, height); XFlush(the_environment.the_display); } XDrawRectangle(the_environment.the_display, the_environment.back_window, the_environment.xor_gc, x,y, width, height); *xi = bevent->x - xoffset; *yi = bevent->y - yoffset; } int resize_window(xi, yi, widthi, heighti, xc, yc, minwidth, minheight) int *xi, *yi; /* Initial x and y position of window */ int *widthi, *heighti; /* Initial width and heigt of window */ int xc, yc; /* location of mouse when clicked on */ int minwidth, minheight; /* minimum width and height of window */ { int x, y; /* x and y coordinates of flashing window. they will not change once they are set. */ int nx, ny; int px, py; int width, height; int nwidth, nheight; short top_click, right_click; XEvent event; XButtonReleasedEvent *bevent; XPointerMovedEvent *mevent; width = *widthi; height = *heighti; x = *xi; y = *yi; if (((int) (*xi + (*widthi / 2))) < xc) { right_click = 1; } else { right_click = 0; } if (((int) (*yi + (*heighti / 2))) < yc) { top_click = 1; } else { top_click = 0; } XDrawRectangle(the_environment.the_display, the_environment.back_window, the_environment.xor_gc, x,y, width, height); for(;;) { XNextEvent(the_environment.the_display, &event); if (event.type == ButtonRelease) { bevent = (XButtonReleasedEvent *) &event; if (bevent->button == user_bindings.resize.button) break; } else if (event.type == MotionNotify) { mevent = (XPointerMovedEvent *) &event; px = mevent->x; py = mevent->y; } if (right_click) { nwidth = (int) px - x; nx = x; } else { nwidth = (int) *xi - px + *widthi; nx = px; } if (top_click) { nheight = (int) py - y; ny = y; } else { nheight = (int) *yi - py + *heighti; ny = py; } if (nwidth < minwidth) continue; if (nheight < minheight) continue; XDrawRectangle(the_environment.the_display, the_environment.back_window, the_environment.xor_gc, x,y, width, height); width = nwidth; height = nheight; x = nx; y = ny; XDrawRectangle(the_environment.the_display, the_environment.back_window, the_environment.xor_gc, x,y, width, height); XFlush(the_environment.the_display); } XDrawRectangle(the_environment.the_display, the_environment.back_window, the_environment.xor_gc, x,y, width, height); if (width < minwidth) return (-1); if (height < minheight) return (-1); *xi = x; *yi = y; *widthi = (int) width; *heighti = (int) height; return (1); }