gboolean mouse_xy_movement(GtkWidget *widget, GdkEventMotion *event) { // caught a mouse movement event double coordx, coordy; gchar *buffer; int excode; select_t *new_select = select_create(); select_t *select_added = select_create(); select_t *select_omitted = select_create(); if (!fldstate.mouse_selection) fldstate.mouse_selection = select_create(); coordx = event->x; coordy = event->y; pixel_to_field(&coordx, &coordy); if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) { coordx = round(coordx); coordy = round(coordy); } if (fldstate.mouse_clicked == 0x1 && mouse_currentMode == SELECTONE) { // click drag // get what's currently in selection rectangle new_select = field_select_in_rectangle(new_select, fldstate.mouse_clickx, fldstate.mouse_clicky, coordx, coordy, false); // then find what's been added, what's gone select_add_multiple(select_added, new_select); select_add_multiple(select_omitted, fldstate.mouse_selection); select_remove_multiple(select_added, fldstate.mouse_selection); select_remove_multiple(select_omitted, new_select); // Store new set select_clear(fldstate.mouse_selection); select_add_multiple(fldstate.mouse_selection, new_select); select_update_center(fldstate.mouse_selection); // add new dots if (event->state == (GDK_BUTTON_PRESS_MASK | GDK_CONTROL_MASK)) { //select_push_all(&pstate.select, &select_added, true); //select_add_multiple(&pstate.select, &select_omitted, true); select_toggle_multiple(pstate.select, select_added); select_toggle_multiple(pstate.select, select_omitted); } else if (event->state == GDK_BUTTON_PRESS_MASK) { // normal or shift-clicked //select_push_all(&pstate.select, &select_added, false); //pstate.select = select_drop_multiple(pstate.select, select_omitted); select_add_multiple(pstate.select, select_added); // drop ommitted dots select_remove_multiple(pstate.select, select_omitted); } } else fldstate.mouse_selection = NULL; fldstate.mousex = coordx; fldstate.mousey = coordy; // store mouse event excode = fieldrel_convert_xy_to_relation(&coordx, &coordy, &buffer); select_added = select_destroy(select_added); select_omitted = select_destroy(select_omitted); new_select = select_destroy(new_select); if (excode == -1) return FALSE; gtk_statusbar_pop(GTK_STATUSBAR(statusbar), GPOINTER_TO_INT(context_id)); gtk_statusbar_push(GTK_STATUSBAR(statusbar), GPOINTER_TO_INT(context_id), buffer); g_free(buffer); dr_canvas_refresh(drill); return TRUE; }
gboolean mouse_unclicked(GtkWidget *widget, GdkEventButton *event) { // handle un-click events on canvas double x, y; int index; int form_index; form_child_t *form2; select_t *select = pstate.select; select_t *form_select = select_create(); form_coord_attr_t form_attr; //double x1, y1; form_child_t *form; form = pshow->sets->currset->forms; x = event->x; y = event->y; pixel_to_field(&x, &y); if (event->button == 1) { switch(mouse_currentMode) { case SELECTONE: select_add_multiple_forms(form_select, select); // move a performer mouse_clickx = x - mouse_clickx; mouse_clicky = y - mouse_clicky; form = form_find_selected_with_endpoint(form_select, fldstate.mouse_clickx, fldstate.mouse_clicky); if (form) { //select_remove_form(form_select, form->parent->index); select_remove_form(form_select, form_child_get_index(form)); } if ((event->state & ~GDK_SHIFT_MASK)== GDK_BUTTON_PRESS_MASK) { // regular click // move dots if (!mouse_discarded && form_endpoint_contains_coords(form, fldstate.mouse_clickx, fldstate.mouse_clicky)) { // move forms while (form && form_endpoint_contains_coords(form, fldstate.mouse_clickx, fldstate.mouse_clicky)) { if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) { // Move on a 1-step grid //form_move_endpoint_grid(form, fldstate.mouse_clickx, fldstate.mouse_clicky, x, y); form_move_endpoint(form, fldstate.mouse_clickx, fldstate.mouse_clicky, x, y, 1.0); } else { // move off of the grid form_move_endpoint(form, fldstate.mouse_clickx, fldstate.mouse_clicky, x, y, 0.0); } if ((form2 = form_find_selected_with_endpoint_hole(form_select, x, y)) != NULL) { // Move dot into endpoint hole //select_remove_form(form_select, form2->parent->index); select_remove_form(form_select, form_child_get_index(form2)); form_contains_coords(form2, &form_attr, x, y); index = form_attr.formindex; //index = form_find_index_with_coords(form2, x, y); form_add_index_to_hole_with_coords(form2, index, x, y); } if ((form = form_find_selected_with_endpoint(form_select, fldstate.mouse_clickx, fldstate.mouse_clicky)) != NULL) { // remove form from checking //select_remove_form(form_select, form->parent->index); select_remove_form(form_select, form_child_get_index(form)); } } select_update_center(pstate.select); dr_canvas_refresh(drill); } else if ((mouse_clickx != 0 || mouse_clicky != 0) && !mouse_discarded) { // move a selected dot if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) { //coords_movexy_grid(mouse_clickx, mouse_clicky); coords_selected_movexy_grid(pshow->sets->currset->coords, pstate.select, mouse_clickx, mouse_clicky); } else { //coords_movexy(mouse_clickx, mouse_clicky); coords_selected_movexy(pshow->sets->currset->coords, pstate.select, mouse_clickx, mouse_clicky); } select_update_center(pstate.select); dr_canvas_refresh(drill); } } break; case ADDFORM: // add a form select_head(pstate.select); form = form_container_get_form_child(pshow->topforms, select_get_form(pstate.select)); form_set_endpoint(form, 0, 0, x, y, 0.0); form_set_endpoint(form, 0, 0, fldstate.mouse_clickx, fldstate.mouse_clicky, 0.0); form_add_to_current_set(form); form_update_line(form); mouse_currentMode = SELECTONE; select_update_center(pstate.select); dr_canvas_refresh(drill); break; } } else if (event->button == 3) { // right-click if ((form_find_with_coords(form_select, pstate.setnum, x, y))) { select_head(form_select); //form = form_find_with_coords(pshow->sets->currset->forms, x, y); while ((form_index = select_get_form_advance(form_select)) != -1) { form = form_container_get_form_child(pshow->topforms, form_index); //index = form_find_index_with_coords(form, x, y); form_contains_coords(form, &form_attr, x, y); index = form_attr.realindex; //printf("%i\n", index); if (index != -1) form_unmanage_dot(form, index); } } } fldstate.mouse_clicked = 0; select_destroy(form_select); dr_canvas_refresh(drill); return TRUE; }
/* in order to save builtin numbers, create a single socket function with * options socket_request(SockOperation,....) */ xsbBool xsb_socket_request(CTXTdecl) { int ecode = 0; /* error code for socket ops */ int timeout_flag; SOCKET sock_handle; int domain, portnum; SOCKADDR_IN socket_addr; struct linger sock_linger_opt; int rc; char *message_buffer = NULL; /* initialized to keep compiler happy */ UInteger msg_len = 0; /* initialized to keep compiler happy */ char char_read; switch (ptoc_int(CTXTc 1)) { case SOCKET_ROOT: /* this is the socket() request */ /* socket_request(SOCKET_ROOT,+domain,-socket_fd,-Error,_,_,_) Currently only AF_INET domain */ domain = (int)ptoc_int(CTXTc 2); if (!translate_domain(domain, &domain)) { return FALSE; } sock_handle = socket(domain, SOCK_STREAM, IPPROTO_TCP); /* error handling */ if (BAD_SOCKET(sock_handle)) { ecode = XSB_SOCKET_ERRORCODE; perror("SOCKET_REQUEST"); } else { ecode = SOCK_OK; } ctop_int(CTXTc 3, (SOCKET) sock_handle); return set_error_code(CTXTc ecode, 4, "SOCKET_REQUEST"); case SOCKET_BIND: /* socket_request(SOCKET_BIND,+domain,+sock_handle,+port,-Error,_,_) Currently only supports AF_INET */ sock_handle = (SOCKET) ptoc_int(CTXTc 3); portnum = (int)ptoc_int(CTXTc 4); domain = (int)ptoc_int(CTXTc 2); if (!translate_domain(domain, &domain)) { return FALSE; } /* Bind server to the agreed upon port number. ** See commdef.h for the actual port number. */ FillWithZeros(socket_addr); socket_addr.sin_port = htons((unsigned short)portnum); socket_addr.sin_family = AF_INET; #ifndef WIN_NT socket_addr.sin_addr.s_addr = htonl(INADDR_ANY); #endif rc = bind(sock_handle, (PSOCKADDR) &socket_addr, sizeof(socket_addr)); /* error handling */ if (SOCKET_OP_FAILED(rc)) { ecode = XSB_SOCKET_ERRORCODE; perror("SOCKET_BIND"); } else ecode = SOCK_OK; return set_error_code(CTXTc ecode, 5, "SOCKET_BIND"); case SOCKET_LISTEN: /* socket_request(SOCKET_LISTEN,+sock_handle,+length,-Error,_,_,_) */ sock_handle = (SOCKET) ptoc_int(CTXTc 2); rc = listen(sock_handle, (int)ptoc_int(CTXTc 3)); /* error handling */ if (SOCKET_OP_FAILED(rc)) { ecode = XSB_SOCKET_ERRORCODE; perror("SOCKET_LISTEN"); } else ecode = SOCK_OK; return set_error_code(CTXTc ecode, 4, "SOCKET_LISTEN"); case SOCKET_ACCEPT: timeout_flag = socket_accept(CTXTc (SOCKET *)&rc, (int)pflags[SYS_TIMER]); if (timeout_flag == TIMED_OUT) { return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND"); } else { /* error handling */ if (BAD_SOCKET(rc)) { ecode = XSB_SOCKET_ERRORCODE; perror("SOCKET_ACCEPT"); sock_handle = rc; /* shut up warning */ } else { sock_handle = rc; /* accept() returns sock_out */ ecode = SOCK_OK; } ctop_int(CTXTc 3, (SOCKET) sock_handle); return set_error_code(CTXTc ecode, 4, "SOCKET_ACCEPT"); } case SOCKET_CONNECT: { /* socket_request(SOCKET_CONNECT,+domain,+sock_handle,+port, +hostname,-Error) */ timeout_flag = socket_connect(CTXTc &rc, (int)pflags[SYS_TIMER]); if (timeout_flag == TIMED_OUT) { return set_error_code(CTXTc TIMEOUT_ERR, 6, "SOCKET_CONNECT"); } else if (timeout_flag == TIMER_SETUP_ERR) { return set_error_code(CTXTc TIMER_SETUP_ERR, 6, "SOCKET_CONNECT"); } else { /* error handling */ if (SOCKET_OP_FAILED(rc)) { ecode = XSB_SOCKET_ERRORCODE; perror("SOCKET_CONNECT"); /* close, because if connect() fails then socket becomes unusable */ closesocket(ptoc_int(CTXTc 3)); } else { ecode = SOCK_OK; } return set_error_code(CTXTc ecode, 6, "SOCKET_CONNECT"); } } case SOCKET_CLOSE: /* socket_request(SOCKET_CLOSE,+sock_handle,-Error,_,_,_,_) */ sock_handle = (SOCKET)ptoc_int(CTXTc 2); /* error handling */ rc = closesocket(sock_handle); if (SOCKET_OP_FAILED(rc)) { ecode = XSB_SOCKET_ERRORCODE; perror("SOCKET_CLOSE"); } else ecode = SOCK_OK; return set_error_code(CTXTc ecode, 3, "SOCKET_CLOSE"); case SOCKET_RECV: /* socket_request(SOCKET_RECV,+Sockfd, -Msg, -Error,_,_,_) */ // TODO: consider adding protection against interrupts, EINTR, like // in socket_get0. timeout_flag = socket_recv(CTXTc &rc, &message_buffer, &msg_len, (int)pflags[SYS_TIMER]); if (timeout_flag == TIMED_OUT) { return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND"); } else { /* error handling */ switch (rc) { case SOCK_OK: ecode = SOCK_OK; break; case SOCK_READMSG_FAILED: ecode = XSB_SOCKET_ERRORCODE; perror("SOCKET_RECV"); break; case SOCK_READMSG_EOF: ecode = SOCK_EOF; break; case SOCK_HEADER_LEN_MISMATCH: ecode = XSB_SOCKET_ERRORCODE; break; default: xsb_abort("XSB bug: [SOCKET_RECV] invalid return code from readmsg"); } if (message_buffer != NULL) { /* use message_buffer+XSB_MSG_HEADER_LENGTH because the first XSB_MSG_HEADER_LENGTH bytes are for the message length header */ ctop_string(CTXTc 3, (char*)message_buffer+XSB_MSG_HEADER_LENGTH); mem_dealloc(message_buffer,msg_len,OTHER_SPACE); } else { /* this happens at the end of a file */ ctop_string(CTXTc 3, (char*)""); } return set_error_code(CTXTc ecode, 4, "SOCKET_RECV"); } case SOCKET_SEND: /* socket_request(SOCKET_SEND,+Sockfd, +Msg, -Error,_,_,_) */ timeout_flag = socket_send(CTXTc &rc, (int)pflags[SYS_TIMER]); if (timeout_flag == TIMED_OUT) { return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND"); } else { /* error handling */ if (SOCKET_OP_FAILED(rc)) { ecode = XSB_SOCKET_ERRORCODE; perror("SOCKET_SEND"); } else { ecode = SOCK_OK; } return set_error_code(CTXTc ecode, 4, "SOCKET_SEND"); } case SOCKET_GET0: /* socket_request(SOCKET_GET0,+Sockfd,-C,-Error,_,_,_) */ message_buffer = &char_read; timeout_flag = socket_get0(CTXTc &rc, message_buffer, (int)pflags[SYS_TIMER]); if (timeout_flag == TIMED_OUT) { return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND"); } else { /*error handling */ switch (rc) { case 1: ctop_int(CTXTc 3,(unsigned char)message_buffer[0]); ecode = SOCK_OK; break; case 0: ecode = SOCK_EOF; break; default: ctop_int(CTXTc 3,-1); perror("SOCKET_GET0"); ecode = XSB_SOCKET_ERRORCODE; } return set_error_code(CTXTc ecode, 4, "SOCKET_GET0"); } case SOCKET_PUT: /* socket_request(SOCKET_PUT,+Sockfd,+C,-Error_,_,_) */ timeout_flag = socket_put(CTXTc &rc, (int)pflags[SYS_TIMER]); if (timeout_flag == TIMED_OUT) { return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND"); } else { /* error handling */ if (rc == 1) { ecode = SOCK_OK; } else if (SOCKET_OP_FAILED(rc)) { ecode = XSB_SOCKET_ERRORCODE; perror("SOCKET_PUT"); } return set_error_code(CTXTc ecode, 4, "SOCKET_PUT"); } case SOCKET_SET_OPTION: { /* socket_request(SOCKET_SET_OPTION,+Sockfd,+OptionName,+Value,_,_,_) */ char *option_name = ptoc_string(CTXTc 3); sock_handle = (SOCKET)ptoc_int(CTXTc 2); /* Set the "linger" parameter to a small number of seconds */ if (0==strcmp(option_name,"linger")) { int linger_time=(int)ptoc_int(CTXTc 4); if (linger_time < 0) { sock_linger_opt.l_onoff = FALSE; sock_linger_opt.l_linger = 0; } else { sock_linger_opt.l_onoff = TRUE; sock_linger_opt.l_linger = linger_time; } if (SETSOCKOPT(sock_handle, SOL_SOCKET, SO_LINGER, &sock_linger_opt, sizeof(sock_linger_opt)) < 0) { xsb_warn(CTXTc "[SOCKET_SET_OPTION] Cannot set socket linger time"); return FALSE; } }else { xsb_warn(CTXTc "[SOCKET_SET_OPTION] Invalid option, `%s'", option_name); return FALSE; } return TRUE; } case SOCKET_SET_SELECT: { /*socket_request(SOCKET_SET_SELECT,+connection_name, +R_sockfd,+W_sockfd,+E_sockfd) */ prolog_term R_sockfd, W_sockfd, E_sockfd; int i, connection_count; int rmax_fd=0, wmax_fd=0, emax_fd=0; char *connection_name = ptoc_string(CTXTc 2); /* bind fds to input arguments */ R_sockfd = reg_term(CTXTc 3); W_sockfd = reg_term(CTXTc 4); E_sockfd = reg_term(CTXTc 5); /* initialize the array of connect_t structure for select call */ init_connections(CTXT); SYS_MUTEX_LOCK(MUTEX_SOCKETS); /* check whether the same connection name exists */ for (i=0;i<MAXCONNECT;i++) { if ((connections[i].empty_flag==FALSE) && (strcmp(connection_name,connections[i].connection_name)==0)) xsb_abort("[SOCKET_SET_SELECT] Connection `%s' already exists!", connection_name); } /* check whether there is empty slot left for connection */ if ((connection_count=checkslot())<MAXCONNECT) { if (connections[connection_count].connection_name == NULL) { connections[connection_count].connection_name = connection_name; connections[connection_count].empty_flag = FALSE; /* call the utility function separately to take the fds in */ list_sockfd(R_sockfd, &connections[connection_count].readset, &rmax_fd, &connections[connection_count].read_fds, &connections[connection_count].sizer); list_sockfd(W_sockfd, &connections[connection_count].writeset, &wmax_fd, &connections[connection_count].write_fds, &connections[connection_count].sizew); list_sockfd(E_sockfd, &connections[connection_count].exceptionset, &emax_fd,&connections[connection_count].exception_fds, &connections[connection_count].sizee); connections[connection_count].maximum_fd = xsb_max(xsb_max(rmax_fd,wmax_fd), emax_fd); } else /* if this one is reached, it is probably a bug */ xsb_abort("[SOCKET_SET_SELECT] All connections are busy!"); } else xsb_abort("[SOCKET_SET_SELECT] Max number of collections exceeded!"); SYS_MUTEX_UNLOCK(MUTEX_SOCKETS); return TRUE; } case SOCKET_SELECT: { /* socket_request(SOCKET_SELECT,+connection_name, +timeout -avail_rsockfds,-avail_wsockfds, -avail_esockfds,-ecode) Returns 3 prolog_terms for available socket fds */ prolog_term Avail_rsockfds, Avail_wsockfds, Avail_esockfds; prolog_term Avail_rsockfds_tail, Avail_wsockfds_tail, Avail_esockfds_tail; int maxfd; int i; /* index for connection_count */ char *connection_name = ptoc_string(CTXTc 2); struct timeval *tv; prolog_term timeout_term; int timeout =0; int connectname_found = FALSE; int count=0; SYS_MUTEX_LOCK(MUTEX_SOCKETS); /* specify the time out */ timeout_term = reg_term(CTXTc 3); if (isointeger(timeout_term)) { timeout = (int)oint_val(timeout_term); /* initialize tv */ tv = (struct timeval *)mem_alloc(sizeof(struct timeval),LEAK_SPACE); tv->tv_sec = timeout; tv->tv_usec = 0; } else tv = NULL; /* no timeouts */ /* initialize the prolog term */ Avail_rsockfds = p2p_new(CTXT); Avail_wsockfds = p2p_new(CTXT); Avail_esockfds = p2p_new(CTXT); /* bind to output arguments */ Avail_rsockfds = reg_term(CTXTc 4); Avail_wsockfds = reg_term(CTXTc 5); Avail_esockfds = reg_term(CTXTc 6); Avail_rsockfds_tail = Avail_rsockfds; Avail_wsockfds_tail = Avail_wsockfds; Avail_esockfds_tail = Avail_esockfds; /* // This was wrong. Lists are now made inside test_ready() c2p_list(CTXTc Avail_rsockfds_tail); c2p_list(CTXTc Avail_wsockfds_tail); c2p_list(CTXTc Avail_esockfds_tail); */ for (i=0; i < MAXCONNECT; i++) { /* find the matching connection_name to select */ if(connections[i].empty_flag==FALSE) { if (strcmp(connection_name, connections[i].connection_name) == 0) { connectname_found = TRUE; count = i; break; } } } if( i >= MAXCONNECT ) /* if no matching connection_name */ xsb_abort("[SOCKET_SELECT] connection `%s' doesn't exist", connection_name); /* compute maxfd for select call */ maxfd = connections[count].maximum_fd + 1; /* FD_SET all sockets */ set_sockfd( CTXTc count ); /* test whether the socket fd is available */ rc = select(maxfd, &connections[count].readset, &connections[count].writeset, &connections[count].exceptionset, tv); /* error handling */ if (rc == 0) /* timed out */ ecode = TIMEOUT_ERR; else if (SOCKET_OP_FAILED(rc)) { perror("SOCKET_SELECT"); ecode = XSB_SOCKET_ERRORCODE; } else { /* no error */ ecode = SOCK_OK; /* call the utility function to return the available socket fds */ test_ready(CTXTc &Avail_rsockfds_tail, &connections[count].readset, connections[count].read_fds,connections[count].sizer); test_ready(CTXTc &Avail_wsockfds_tail, &connections[count].writeset, connections[count].write_fds,connections[count].sizew); test_ready(CTXTc &Avail_esockfds_tail,&connections[count].exceptionset, connections[count].exception_fds,connections[count].sizee); } SYS_MUTEX_UNLOCK(MUTEX_SOCKETS); if (tv) mem_dealloc((struct timeval *)tv,sizeof(struct timeval),LEAK_SPACE); SQUASH_LINUX_COMPILER_WARN(connectname_found) ; return set_error_code(CTXTc ecode, 7, "SOCKET_SELECT"); } case SOCKET_SELECT_DESTROY: { /*socket_request(SOCKET_SELECT_DESTROY, +connection_name) */ char *connection_name = ptoc_string(CTXTc 2); select_destroy(CTXTc connection_name); return TRUE; } default: xsb_warn(CTXTc "[SOCKET_REQUEST] Invalid socket request %d", (int) ptoc_int(CTXTc 1)); return FALSE; } /* This trick would report a bug, if a newly added case doesn't have a return clause */ xsb_bug("SOCKET_REQUEST case %d has no return clause", ptoc_int(CTXTc 1)); }