static void draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int overlay, int which) { struct frame *f = XFRAME (WINDOW_FRAME (w)); struct draw_fringe_bitmap_params p; struct fringe_bitmap *fb; int period; int face_id = DEFAULT_FACE_ID; int offset, header_line_height; p.overlay_p = (overlay & 1) == 1; p.cursor_p = (overlay & 2) == 2; if (which != NO_FRINGE_BITMAP) { offset = 0; } else if (left_p) { which = row->left_fringe_bitmap; face_id = row->left_fringe_face_id; offset = row->left_fringe_offset; } else { which = row->right_fringe_bitmap; face_id = row->right_fringe_face_id; offset = row->right_fringe_offset; } if (face_id == DEFAULT_FACE_ID) { Lisp_Object face = fringe_faces[which]; face_id = NILP (face) ? lookup_named_face (f, Qfringe, 0) : lookup_derived_face (f, face, FRINGE_FACE_ID, 0); if (face_id < 0) face_id = FRINGE_FACE_ID; } fb = get_fringe_bitmap_data (which); period = fb->period; /* Convert row to frame coordinates. */ p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset; p.which = which; p.bits = fb->bits; p.wd = fb->width; p.h = fb->height; p.dh = (period > 0 ? (p.y % period) : 0); p.h -= p.dh; /* Adjust y to the offset in the row to start drawing the bitmap. */ switch (fb->align) { case ALIGN_BITMAP_CENTER: p.y += (row->height - p.h) / 2; break; case ALIGN_BITMAP_BOTTOM: p.y += (row->visible_height - p.h); break; case ALIGN_BITMAP_TOP: break; } p.face = FACE_FROM_ID (f, face_id); if (p.face == NULL) { /* This could happen after clearing face cache. But it shouldn't happen anymore. ++kfs */ return; } PREPARE_FACE_FOR_DISPLAY (f, p.face); /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill the fringe. */ p.bx = -1; header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y)); p.ny = row->visible_height; if (left_p) { int wd = WINDOW_LEFT_FRINGE_WIDTH (w); int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? LEFT_MARGIN_AREA : TEXT_AREA)); if (p.wd > wd) p.wd = wd; p.x = x - p.wd - (wd - p.wd) / 2; if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny) { /* If W has a vertical border to its left, don't draw over it. */ wd -= ((!WINDOW_LEFTMOST_P (w) && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)) ? 1 : 0); p.bx = x - wd; p.nx = wd; } } else { int x = window_box_right (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? RIGHT_MARGIN_AREA : TEXT_AREA)); int wd = WINDOW_RIGHT_FRINGE_WIDTH (w); if (p.wd > wd) p.wd = wd; p.x = x + (wd - p.wd) / 2; /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill the fringe. */ if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny) { p.bx = x; p.nx = wd; } } FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p); }
void viper_kmio_dispatch(gint32 keystroke,MEVENT *mouse_event) { extern VIPER *viper; static WINDOW *event_window=NULL; static MEVENT previous_mouse_event; static VIPER_WKEY_FUNC func; static gint event_mode=0; VIPER_KMIO_HOOK kmio_dispatch_hook; gint beg_x,beg_y; gint max_x,max_y; MEVENT *new_mouse=NULL; /* strictly for */ MEVENT *old_mouse=NULL; /* for readability */ #if !defined(_NO_GPM) && defined(__linux) extern int gpm_fd; #endif // run the dispatch pre-processing hook if(viper->kmio_dispatch_hook[KMIO_HOOK_ENTER] != NULL) { kmio_dispatch_hook=viper->kmio_dispatch_hook[KMIO_HOOK_ENTER]; keystroke=kmio_dispatch_hook(keystroke); } if(keystroke == -1) return; if(keystroke==KEY_RESIZE) { viper_event_run(VIPER_EVENT_BROADCAST,"term-resized"); /* todo event handle for screen window instead */ viper_screen_redraw(REDRAW_ALL | REDRAW_BACKGROUND); } if(keystroke==KEY_MOUSE && mouse_event!=NULL) { new_mouse=mouse_event; old_mouse=&previous_mouse_event; if((new_mouse->bstate & REPORT_MOUSE_POSITION) && event_mode==EVENTMODE_MOVE) { viper_mvwin_rel(event_window,new_mouse->x-old_mouse->x, new_mouse->y-old_mouse->y); memcpy(old_mouse,new_mouse,sizeof(MEVENT)); } if((new_mouse->bstate & REPORT_MOUSE_POSITION) && event_mode==EVENTMODE_RESIZE) { viper_wresize_rel(event_window,new_mouse->x-old_mouse->x, new_mouse->y-old_mouse->y); memcpy(old_mouse,new_mouse,sizeof(MEVENT)); } /* check for a button press and a window hit */ if((new_mouse->bstate & BUTTON1_PRESSED) && event_mode==EVENTMODE_IDLE) { event_window=viper_deck_hit_test(new_mouse->x,new_mouse->y); if(event_window!=NULL) { viper_window_set_top(event_window); memcpy(old_mouse,new_mouse,sizeof(MEVENT)); getbegyx(WINDOW_FRAME(event_window),beg_y,beg_x); getmaxyx(WINDOW_FRAME(event_window),max_y,max_x); if(new_mouse->x==(beg_x+max_x-1) && new_mouse->y==(beg_y+max_y)-1) event_mode=EVENTMODE_RESIZE; else event_mode=EVENTMODE_MOVE; } else event_mode=EVENTMODE_IDLE; } if(new_mouse->bstate & BUTTON1_RELEASED) { if(!(new_mouse->bstate & REPORT_MOUSE_POSITION)) { if(event_mode==EVENTMODE_MOVE) viper_mvwin_rel(event_window, new_mouse->x-old_mouse->x,new_mouse->y-old_mouse->y); /* resize window */ if(event_mode==EVENTMODE_RESIZE) { viper_wresize_rel(event_window,new_mouse->x-old_mouse->x, new_mouse->y-old_mouse->y); viper_screen_redraw(REDRAW_ALL); } } event_window=NULL; event_mode=EVENTMODE_IDLE; } if(new_mouse->bstate & BUTTON1_CLICKED) { event_window=viper_deck_hit_test(new_mouse->x,new_mouse->y); if(event_window!=NULL) { viper_window_set_top(event_window); viper_window_redraw(event_window); getbegyx(WINDOW_FRAME(event_window),beg_y,beg_x); getmaxyx(WINDOW_FRAME(event_window),max_y,max_x); if(new_mouse->x==(beg_x+max_x-2) && new_mouse->y==beg_y) { viper_window_close(event_window); keystroke=-1; } if(new_mouse->x==(beg_x+max_x-4) && new_mouse->y==beg_y) { viper_window_hide(event_window); viper_deck_cycle(VECTOR_BOTTOM_TO_TOP); keystroke=-1; } } event_window=NULL; event_mode=EVENTMODE_IDLE; } if(new_mouse->bstate & BUTTON1_DOUBLE_CLICKED) { event_window=viper_deck_hit_test(new_mouse->x,new_mouse->y); if(event_window!=NULL) { viper_window_set_top(event_window); viper_window_redraw(event_window); } event_window=NULL; event_mode=EVENTMODE_IDLE; } } // run the post-processing dispatch hook if(viper->kmio_dispatch_hook[KMIO_HOOK_LEAVE] != NULL) { kmio_dispatch_hook=viper->kmio_dispatch_hook[KMIO_HOOK_LEAVE]; keystroke=kmio_dispatch_hook(keystroke); } // pass keystroke on to toplevel window if(keystroke != KEY_RESIZE && keystroke != -1) { func=viper_window_get_key_func(TOPMOST_WINDOW); if(func!=NULL) func(keystroke,(gpointer)TOPMOST_WINDOW); } #if !defined(_NO_GPM) && defined(__linux) if(gpm_fd>0) { viper_kmio_show_mouse(new_mouse); viper_screen_redraw(REDRAW_ALL); } #endif }
/* * This is the only callback provided for horizontal scrollbars. It * should be able to handle all of the scrollbar events in * scroll_action (see lwlib.h). The client data will be of type * scroll_event (see lwlib.h). */ static void x_update_horizontal_scrollbar_callback (Widget widget, LWLIB_ID id, XtPointer client_data) { scroll_event *data = (scroll_event *) client_data; struct device *d = get_device_from_display (XtDisplay (widget)); struct frame *f = x_any_window_to_frame (d, XtWindow (widget)); Lisp_Object win, frame; struct window_mirror *mirror; if (!f) return; mirror = find_scrollbar_window_mirror (f, id); if (!mirror) return; win = real_window (mirror, 1); if (NILP (win)) return; frame = WINDOW_FRAME (XWINDOW (win)); /* It seems that this is necessary whenever signal_special_Xt_user_event() is called. #### Why??? */ DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d); switch (data->action) { case SCROLLBAR_LINE_UP: signal_special_Xt_user_event (frame, Qscrollbar_char_left, win); break; case SCROLLBAR_LINE_DOWN: signal_special_Xt_user_event (frame, Qscrollbar_char_right, win); break; case SCROLLBAR_PAGE_UP: signal_special_Xt_user_event (frame, Qscrollbar_page_left, win); break; case SCROLLBAR_PAGE_DOWN: signal_special_Xt_user_event (frame, Qscrollbar_page_right, win); break; case SCROLLBAR_TOP: signal_special_Xt_user_event (frame, Qscrollbar_to_left, win); break; case SCROLLBAR_BOTTOM: signal_special_Xt_user_event (frame, Qscrollbar_to_right, win); break; case SCROLLBAR_CHANGE: inhibit_slider_size_change = 0; break; case SCROLLBAR_DRAG: inhibit_slider_size_change = 1; /* #### Fix the damn toolkit code so they all work the same way. Lucid is the one mostly wrong.*/ #if defined (LWLIB_SCROLLBARS_LUCID) || defined (LWLIB_SCROLLBARS_ATHENA3D) signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag, (Fcons (win, make_int (data->slider_value)))); #else signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag, (Fcons (win, make_int (data->slider_value - 1)))); #endif break; default: break; } }
static void draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int overlay, int which) { struct frame *f = XFRAME (WINDOW_FRAME (w)); struct draw_fringe_bitmap_params p; struct fringe_bitmap *fb; int period; int face_id = DEFAULT_FACE_ID; int offset, header_line_height; p.overlay_p = (overlay & 1) == 1; p.cursor_p = (overlay & 2) == 2; if (which != NO_FRINGE_BITMAP) { offset = 0; } else if (left_p) { which = row->left_fringe_bitmap; face_id = row->left_fringe_face_id; offset = row->left_fringe_offset; } else { which = row->right_fringe_bitmap; face_id = row->right_fringe_face_id; offset = row->right_fringe_offset; } if (face_id == DEFAULT_FACE_ID) { Lisp_Object face = fringe_faces[which]; face_id = NILP (face) ? lookup_named_face (f, Qfringe, false) : lookup_derived_face (f, face, FRINGE_FACE_ID, 0); if (face_id < 0) face_id = FRINGE_FACE_ID; } fb = get_fringe_bitmap_data (which); period = fb->period; /* Convert row to frame coordinates. */ p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset; p.which = which; p.bits = fb->bits; p.wd = fb->width; p.h = fb->height; p.dh = (period > 0 ? (p.y % period) : 0); p.h -= p.dh; /* Adjust y to the offset in the row to start drawing the bitmap. */ switch (fb->align) { case ALIGN_BITMAP_CENTER: p.y += (row->height - p.h) / 2; break; case ALIGN_BITMAP_BOTTOM: p.y += (row->visible_height - p.h); break; case ALIGN_BITMAP_TOP: break; } p.face = FACE_FROM_ID_OR_NULL (f, face_id); if (p.face == NULL) { /* This could happen after clearing face cache. But it shouldn't happen anymore. ++kfs */ return; } prepare_face_for_display (f, p.face); /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill the fringe. */ p.bx = -1; header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y)); p.ny = row->visible_height; if (left_p) { int wd = WINDOW_LEFT_FRINGE_WIDTH (w); int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? LEFT_MARGIN_AREA : TEXT_AREA)); if (p.wd > wd) p.wd = wd; p.x = x - p.wd - (wd - p.wd) / 2; if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny) { /* If W has a vertical border to its left, don't draw over it. */ wd -= ((!WINDOW_LEFTMOST_P (w) /* This could be wrong when we allow window local right dividers - but the window on the left is hard to get. */ && !FRAME_RIGHT_DIVIDER_WIDTH (f) && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w) /* But don't reduce the fringe width if the window has a left margin, because that means we are not in danger of drawing over the vertical border, and OTOH leaving out that one pixel leaves behind traces of the cursor, if it was in column zero before drawing non-empty margin area. */ && w->left_margin_cols == 0) ? 1 : 0); p.bx = x - wd; p.nx = wd; } } else { int x = window_box_right (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? RIGHT_MARGIN_AREA : TEXT_AREA)); int wd = WINDOW_RIGHT_FRINGE_WIDTH (w); if (p.wd > wd) p.wd = wd; p.x = x + (wd - p.wd) / 2; /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill the fringe. */ if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny) { p.bx = x; p.nx = wd; } } if (p.x >= WINDOW_BOX_LEFT_EDGE_X (w) && (p.x + p.wd) <= WINDOW_BOX_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)) FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p); }
/* * This is the only callback provided for vertical scrollbars. It * should be able to handle all of the scrollbar events in * scroll_action (see lwlib.h). The client data will be of type * scroll_event (see lwlib.h). */ static void x_update_vertical_scrollbar_callback (Widget widget, LWLIB_ID id, XtPointer client_data) { /* This function can GC */ scroll_event *data = (scroll_event *) client_data; struct device *d = get_device_from_display (XtDisplay (widget)); struct frame *f = x_any_window_to_frame (d, XtWindow (widget)); Lisp_Object win, frame; struct scrollbar_instance *instance; struct window_mirror *mirror; if (!f) return; mirror = find_scrollbar_window_mirror (f, id); if (!mirror) return; win = real_window (mirror, 1); if (NILP (win)) return; instance = mirror->scrollbar_vertical_instance; frame = WINDOW_FRAME (XWINDOW (win)); /* It seems that this is necessary whenever signal_special_Xt_user_event() is called. #### Why??? */ DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d); switch (data->action) { case SCROLLBAR_LINE_UP: signal_special_Xt_user_event (frame, Qscrollbar_line_up, win); break; case SCROLLBAR_LINE_DOWN: signal_special_Xt_user_event (frame, Qscrollbar_line_down, win); break; /* The Athena scrollbar paging behavior is that of xterms. Depending on where you click the size of the page varies. Motif always does a standard Emacs page. */ case SCROLLBAR_PAGE_UP: #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \ !defined (LWLIB_SCROLLBARS_ATHENA3D) { double tmp = ((double) data->slider_value / (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height); double line = tmp * (double) window_displayed_height (XWINDOW (win)); if (line > -1.0) line = -1.0; signal_special_Xt_user_event (frame, Qscrollbar_page_up, Fcons (win, make_int ((int) line))); } #else signal_special_Xt_user_event (frame, Qscrollbar_page_up, Fcons (win, Qnil)); #endif break; case SCROLLBAR_PAGE_DOWN: #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \ !defined (LWLIB_SCROLLBARS_ATHENA3D) { double tmp = ((double) data->slider_value / (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height); double line = tmp * (double) window_displayed_height (XWINDOW (win)); if (SCROLLBAR_X_POS_DATA(instance).maximum > (SCROLLBAR_X_POS_DATA(instance).slider_size + SCROLLBAR_X_POS_DATA(instance).slider_position)) { if (line < 1.0) line = 1.0; signal_special_Xt_user_event (frame, Qscrollbar_page_down, Fcons (win, make_int ((int) line))); } } #else signal_special_Xt_user_event (frame, Qscrollbar_page_down, Fcons (win, Qnil)); #endif break; case SCROLLBAR_TOP: signal_special_Xt_user_event (frame, Qscrollbar_to_top, win); break; case SCROLLBAR_BOTTOM: signal_special_Xt_user_event (frame, Qscrollbar_to_bottom, win); break; case SCROLLBAR_CHANGE: inhibit_slider_size_change = 0; #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) vertical_drag_in_progress = 0; SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value; SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) = XINT (Fwindow_start (win)); #else stupid_vertical_scrollbar_drag_hack = 0; #endif break; case SCROLLBAR_DRAG: { int value; inhibit_slider_size_change = 1; #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) /* Doing drags with Motif-like scrollbars is a mess, since we want to avoid having the window position jump when you first grab the scrollbar, but we also want to ensure that you can scroll all the way to the top or bottom of the buffer. This can all be replaced with something sane when we get line-based scrolling. */ vertical_drag_in_progress = 1; if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) < 0) { SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value; SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) = XINT (Fwindow_start (win)); } /* Could replace this piecewise linear scrolling with a quadratic through the three points, but I'm not sure that would feel any nicer in practice. */ if (data->slider_value < SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)) { /* We've dragged up; slide linearly from original position to window-start=data.minimum, slider-value=data.minimum. */ if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) <= SCROLLBAR_X_POS_DATA (instance).minimum) { /* shouldn't get here, but just in case */ value = SCROLLBAR_X_POS_DATA (instance).minimum; } else { value = (int) (SCROLLBAR_X_POS_DATA (instance).minimum + (((double) (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) - SCROLLBAR_X_POS_DATA (instance).minimum) * (data->slider_value - SCROLLBAR_X_POS_DATA (instance).minimum)) / (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) - SCROLLBAR_X_POS_DATA (instance).minimum))); } } else { /* We've dragged down; slide linearly from original position to window-start=data.maximum, slider-value=data.maximum. */ if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) >= (SCROLLBAR_X_POS_DATA (instance).maximum - SCROLLBAR_X_POS_DATA (instance).slider_size)) { /* avoid divide by zero */ value = SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance); } else { value = (int) (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) + (((double) (SCROLLBAR_X_POS_DATA (instance).maximum - SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance)) * (data->slider_value - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance))) / (SCROLLBAR_X_POS_DATA (instance).maximum - SCROLLBAR_X_POS_DATA (instance).slider_size - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)))); } } #else stupid_vertical_scrollbar_drag_hack = 0; value = data->slider_value; #endif if (value >= SCROLLBAR_X_POS_DATA (instance).maximum) value = SCROLLBAR_X_POS_DATA (instance).maximum - 1; if (value < SCROLLBAR_X_POS_DATA (instance).minimum) value = SCROLLBAR_X_POS_DATA (instance).minimum; signal_special_Xt_user_event (frame, Qscrollbar_vertical_drag, Fcons (win, make_int (value))); } break; } }