/* Convert the keypress event into a string. */ static unsigned char* lookup_key(XEvent* ev, int* pcount) { KeySym keysym; int count; static unsigned char kbuf[KBUFSIZE]; unsigned char* s; unsigned char* str; count = XLookupString(&ev->xkey, (char*)kbuf, KBUFSIZE, &keysym, NULL); s = NULL; if (IsFunctionKey(keysym) || IsMiscFunctionKey(keysym) || (keysym == XK_Next) || (keysym == XK_Prior) || (keysym == XK_Delete) || (keysym == XK_BackSpace)) { s = get_keycode_value(func_key_table, keysym, kbuf, KBUFSIZE, sun_function_keys); } else if (IsCursorKey(keysym) || IsPFKey(keysym)) { s = get_keycode_value(other_key_table, keysym, kbuf, KBUFSIZE, app_cur_keys); } else { s = get_keycode_value(kp_key_table, keysym, kbuf, KBUFSIZE, app_kp_keys); } if (s != NULL) { *pcount = strlen((char*)s); str = s; } else { str = kbuf; if ((ev->xkey.state & Mod1Mask) && (count == 1)) { if (is_eightbit()) { kbuf[0] |= 0200; *pcount = 1; } else { kbuf[1] = kbuf[0]; kbuf[0] = '\033'; *pcount = 2; } } else { *pcount = count; } } return(str); }
/* Return the next input character after first passing any keyboard input * to the command. If flags & BUF_ONLY is true then only buffered characters are * returned and once the buffer is empty the special value GCC_NULL is * returned. If flags and GET_XEVENTS is true then GCC_NULL is returned * when an X event arrives. */ static int get_com_char(int flags) { XEvent event; struct xeventst *xe; fd_set in_fdset, out_fdset; unsigned char *s; int count, sv; unsigned char mask = is_eightbit() ? 0xff : 0x7f; extern int errno; if (com_stack_top > com_stack) return(*--com_stack_top); if (com_buf_next < com_buf_top) return(*com_buf_next++ & mask); else if (flags & BUF_ONLY) return(GCC_NULL); for (;;) { FD_ZERO(&in_fdset); while (XPending(display) == 0) { if (FD_ISSET(x_fd,&in_fdset)) /* If we get to this point something is wrong * because there is X input available but no * events. Exit the program to avoid looping * forever. */ quit(0); FD_SET(comm_fd,&in_fdset); FD_SET(x_fd,&in_fdset); FD_ZERO(&out_fdset); if (send_count > 0) FD_SET(comm_fd,&out_fdset); do sv = select(fd_width,&in_fdset,&out_fdset,NULL,NULL); while (sv < 0 && errno == EINTR); if (sv < 0) { error("select failed"); quit(-1); } if (FD_ISSET(comm_fd,&out_fdset)) { count = send_count < 100 ? send_count : 100; count = write(comm_fd,send_nxt,count); if (count < 0) { error("failed to write to command"); quit(-1); } send_count -= count; send_nxt += count; } if (FD_ISSET(comm_fd,&in_fdset)) break; } if (FD_ISSET(comm_fd,&in_fdset)) break; XNextEvent(display,&event); if (event.type == KeyPress) { s = lookup_key(&event,&count); if (count != 0) send_string(s,count); } else if (event.type == ClientMessage) { if (event.xclient.format == 32 && event.xclient.data.l[0] == wm_del_win) quit(0); } else if (event.type == MappingNotify) { XRefreshKeyboardMapping(&event.xmapping); } else if (event.type == SelectionRequest) { xe = (struct xeventst *)cmalloc(sizeof(struct xeventst)); xe->xe_type = event.type; xe->xe_window = event.xselectionrequest.owner; xe->xe_time = event.xselectionrequest.time; xe->xe_requestor = event.xselectionrequest.requestor; xe->xe_target = event.xselectionrequest.target; xe->xe_property = event.xselectionrequest.property; push_xevent(xe); if (flags & GET_XEVENTS) return(GCC_NULL); } else if (event.type == SelectionNotify) { xe = (struct xeventst *)cmalloc(sizeof(struct xeventst)); xe->xe_type = event.type; xe->xe_time = event.xselection.time; xe->xe_requestor = event.xselection.requestor; xe->xe_property = event.xselection.property; push_xevent(xe); if (flags & GET_XEVENTS) return(GCC_NULL); } else if (event.type == FocusIn || event.type == FocusOut) { if (event.xfocus.mode != NotifyNormal) continue; switch (event.xfocus.detail) { case NotifyAncestor : case NotifyInferior : case NotifyNonlinear : break; default : continue; } xe = (struct xeventst *)cmalloc(sizeof(struct xeventst)); xe->xe_window = 0; xe->xe_type = event.type; xe->xe_time = event.xselection.time; xe->xe_detail = event.xfocus.detail; push_xevent(xe); if (flags & GET_XEVENTS) return(GCC_NULL); } else { xe = (struct xeventst *)cmalloc(sizeof(struct xeventst)); xe->xe_type = event.type; xe->xe_window = event.xany.window; if (event.type == Expose || event.type == GraphicsExpose) { xe->xe_x = event.xexpose.x; xe->xe_y = event.xexpose.y; xe->xe_width = event.xexpose.width; xe->xe_height = event.xexpose.height; } else { xe->xe_time = event.xbutton.time; xe->xe_x = event.xbutton.x; xe->xe_y = event.xbutton.y; xe->xe_state = event.xbutton.state; xe->xe_button = event.xbutton.button; } push_xevent(xe); if (flags & GET_XEVENTS) return(GCC_NULL); } } count = read(comm_fd,com_buf,COM_BUF_SIZE); if (count <= 0) { if (errno == EWOULDBLOCK) { return(GCC_NULL); } else { return(EOF); } } com_buf_next = com_buf; com_buf_top = com_buf + count; return(*com_buf_next++ & mask); }