/* -*- mode: C; mode: fold; -*- */ #include "config.h" #include "jed-feat.h" /*{{{ Include Files */ #include #include #include #include "jdmacros.h" #include "buffer.h" #include "sysdep.h" #include "keymap.h" #include "misc.h" #include "paste.h" #include "screen.h" #include "ledit.h" #include "ins.h" #include "display.h" #include "hooks.h" /*}}}*/ int (*JMouse_Event_Hook)(void); void (*JMouse_Hide_Mouse_Hook) (int); /*{{{ Static Global Variables */ static SLang_Name_Type *Jed_Default_Mouse_Down_Hook; static SLang_Name_Type *Jed_Mouse_Status_Down_Hook; static SLang_Name_Type *Jed_Default_Mouse_Up_Hook; static SLang_Name_Type *Jed_Mouse_Status_Up_Hook; static SLang_Name_Type *Jed_Default_Mouse_Drag_Hook; static SLang_Name_Type *Jed_Mouse_Status_Drag_Hook; #if JED_HAS_MULTICLICK static SLang_Name_Type *Jed_Mouse_Status_2Click_Hook; static SLang_Name_Type *Jed_Mouse_Status_3Click_Hook; static SLang_Name_Type *Jed_Default_Mouse_2Click_Hook; static SLang_Name_Type *Jed_Default_Mouse_3Click_Hook; #endif static Window_Type *Use_This_Window; static Window_Type *Save_Window; static unsigned int Down_Mask; #ifdef IBMPC_SYSTEM # define JED_MOUSE_MAX_QUEUE_SIZE 8 #else # define JED_MOUSE_MAX_QUEUE_SIZE 64 #endif static JMouse_Type Mouse_Queue [JED_MOUSE_MAX_QUEUE_SIZE]; static JMouse_Type Current_Event; static int Mouse_Queue_Hint; static unsigned char Mouse_Button_Map [3] = { JMOUSE_BUTTON_1, JMOUSE_BUTTON_2, JMOUSE_BUTTON_3 }; /*}}}*/ #ifndef USE_GPM_MOUSE # if defined(__MSDOS__) # if !defined(MSWINDOWS) # include "pcmouse.c" # endif # else # ifdef __os2__ # include "os2mouse.c" # else int (*X_Open_Mouse_Hook)(void); void (*X_Close_Mouse_Hook)(void); # endif /* os2 */ # endif /* ibmpc */ #endif /* NOT USE_GPM_MOUSE */ /* *ap and *bp must have one of values in set (1, 2, 4). */ void jed_map_mouse_buttons (int *ap, int *bp) /*{{{*/ { unsigned char a, b; a = (unsigned char) (*ap >> 1); b = (unsigned char) (*bp >> 1); if ((a > 2) || (b > 2)) return; Mouse_Button_Map [a] = b << 1; } /*}}}*/ int jed_mouse_add_event (JMouse_Type *ev) /*{{{*/ { int save = Mouse_Queue_Hint; /* Search the queue looking for an empty slot. */ while (Mouse_Queue_Hint < JED_MOUSE_MAX_QUEUE_SIZE) { if (Mouse_Queue[Mouse_Queue_Hint].type == 0) { Mouse_Queue [Mouse_Queue_Hint] = *ev; return Mouse_Queue_Hint; } Mouse_Queue_Hint++; } Mouse_Queue_Hint = save; while (Mouse_Queue_Hint > 0) { Mouse_Queue_Hint--; if (Mouse_Queue[Mouse_Queue_Hint].type == 0) { Mouse_Queue [Mouse_Queue_Hint] = *ev; return Mouse_Queue_Hint; } } if (Input_Buffer_Len == 0) { jed_flush_mouse_queue (); Mouse_Queue [0] = *ev; return 0; } return -1; } /*}}}*/ static JMouse_Type *get_mouse_event (unsigned int *type) /*{{{*/ { int queue_pos; JMouse_Type *jm; /* Keyboard input should be ready. If it is not, get out. */ if (0 == input_pending (&Number_Zero)) return NULL; queue_pos = jed_getkey (); if ((queue_pos >= JED_MOUSE_MAX_QUEUE_SIZE) || (queue_pos < 0)) return NULL; jm = Mouse_Queue + queue_pos; /* 1, 2, 4 --> Mouse_Button_Map of 0, 1, 2 */ jm->button = Mouse_Button_Map [jm->button >> 1]; *type = jm->type; jm->type = 0; Mouse_Queue_Hint = queue_pos; return jm; } /*}}}*/ void jed_mouse_get_event_info (void) /*{{{*/ { SLang_push_integer (Current_Event.x); SLang_push_integer (Current_Event.y); SLang_push_integer (Current_Event.state); } /*}}}*/ void jed_flush_mouse_queue (void) /*{{{*/ { unsigned int i; for (i = 0; i < JED_MOUSE_MAX_QUEUE_SIZE; i++) Mouse_Queue[i].type = 0; Mouse_Queue_Hint = 0; } /*}}}*/ static int window_exists (Window_Type *win) /*{{{*/ { Window_Type *w; w = JWindow; do { if (w == win) return 1; w = w->next; } while (w != JWindow); return 0; } /*}}}*/ static int switch_to_event_window (int x, int y, int *linep, int *colp, int *status) /*{{{*/ { Window_Type *w; int delta_y; static int last_status; *status = 0; if (Use_This_Window != NULL) { if (0 == window_exists (Use_This_Window)) { last_status = 0; return -1; } *status = last_status; } else { int top, bot; w = JWindow; do { top = w->top; bot = top + w->rows; if ((y >= top) && (y < bot)) { Use_This_Window = w; break; } if (y == bot) { Use_This_Window = w; *status = 1; break; } w = w->next; } while (w != JWindow); } if (Use_This_Window == NULL) { last_status = 0; return -1; } while (JWindow != Use_This_Window) other_window (); last_status = *status; if (last_status) { *colp = x; return 0; } /* What line does y correspond ??? */ delta_y = y - (Use_This_Window->top - 1 + window_line ()); y = LineNum; #if JED_HAS_LINE_ATTRIBUTES if (delta_y > 0) { Line *l = CLine; while (delta_y && (l != NULL)) { if (0 == (l->flags & JED_LINE_HIDDEN)) delta_y--; l = l->next; y++; } while ((l != NULL) && (l->flags & JED_LINE_HIDDEN)) { l = l->next; y++; } } else if (delta_y < 0) { Line *l = CLine; while (delta_y && (l != NULL)) { if (0 == (l->flags & JED_LINE_HIDDEN)) delta_y++; l = l->prev; y--; } while ((l != NULL) && (l->flags & JED_LINE_HIDDEN)) { l = l->prev; y--; } } #endif *linep = y + delta_y; *colp = JWindow->column + x - 1; return 0; } /*}}}*/ static int do_function (SLang_Name_Type *fun, int line, int col, int button, int shift) /*{{{*/ { int ret = 1; SLang_push_integer (line); SLang_push_integer (col); SLang_push_integer (button); SLang_push_integer (shift); if (SLang_Error) return ret; SLexecute_function (fun); if ((SLang_Error == 0) && SLang_pop_integer (&ret)) ret = 1; return ret; } /*}}}*/ static void switch_to_window (Window_Type *w) /*{{{*/ { if (window_exists (w)) { while (JWindow != w) other_window (); } } /*}}}*/ static int do_mouse_cmd (JMouse_Type *jmouse, unsigned int type) /*{{{*/ { int button, shift; int linenum, column, is_status; int ret; SLang_Name_Type *fun, *default_fun; button = jmouse->button; /* Consistency check */ if (type == JMOUSE_DOWN) { if (Down_Mask & button) { Down_Mask = 0; return 0; } Save_Window = JWindow; } else if ((0 == (Down_Mask & button)) && (type != JMOUSE_DOUBLE_CLICK) && (type != JMOUSE_TRIPLE_CLICK)) { Down_Mask = 0; return 0; } if (Down_Mask == 0) Use_This_Window = NULL; if (-1 == switch_to_event_window (jmouse->x, jmouse->y, &linenum, &column, &is_status)) { Down_Mask = 0; Use_This_Window = NULL; return 0; } default_fun = NULL; switch (type) { case JMOUSE_DRAG: if (is_status) fun = Jed_Mouse_Status_Drag_Hook; else { fun = CBuf->mouse_drag_hook; default_fun = Jed_Default_Mouse_Drag_Hook; } break; #if JED_HAS_MULTICLICK case JMOUSE_DOUBLE_CLICK: if (is_status) fun = Jed_Mouse_Status_2Click_Hook; else { fun = CBuf->mouse_2click_hook; default_fun = Jed_Default_Mouse_2Click_Hook; } break; case JMOUSE_TRIPLE_CLICK: if (is_status) fun = Jed_Mouse_Status_3Click_Hook; else { fun = CBuf->mouse_3click_hook; default_fun = Jed_Default_Mouse_3Click_Hook; } break; #endif case JMOUSE_DOWN: Down_Mask |= button; if (is_status) fun = Jed_Mouse_Status_Down_Hook; else { fun = CBuf->mouse_down_hook; default_fun = Jed_Default_Mouse_Down_Hook; } break; case JMOUSE_UP: Down_Mask &= ~button; if (is_status) fun = Jed_Mouse_Status_Up_Hook; else { fun = CBuf->mouse_up_hook; default_fun = Jed_Default_Mouse_Up_Hook; } break; default: flush_input (); fun = NULL; } if (jmouse->state & JMOUSE_SHIFT) shift = 1; else if (jmouse->state & JMOUSE_CTRL) shift = 2; else shift = 0; ret = -1; if (fun != NULL) { ret = do_function (fun, linenum, column, button, shift); } if ((ret == -1) && (default_fun != NULL)) { ret = do_function (default_fun, linenum, column, button, shift); } if ((type == JMOUSE_UP) && (Down_Mask == 0) && (ret <= 0)) { switch_to_window (Save_Window); Save_Window = NULL; } return ret; } /*}}}*/ int jed_mouse_cmd (void) /*{{{*/ { unsigned int type; JMouse_Type *jmouse; if ((NULL == (jmouse = get_mouse_event (&type))) || (type == JMOUSE_IGNORE_EVENT)) return 0; Current_Event = *jmouse; #if JED_HAS_MULTICLICK if ((-1 == do_mouse_cmd (jmouse, type)) && ((type == JMOUSE_DOUBLE_CLICK) || (type == JMOUSE_TRIPLE_CLICK))) { /* Event multiclick event not handled so simulated click. */ (void) do_mouse_cmd (&Current_Event, JMOUSE_DOWN); (void) do_mouse_cmd (&Current_Event, JMOUSE_UP); } #else (void) do_mouse_cmd (jmouse, type); #endif return 1; } /*}}}*/ void jed_set_current_mouse_window (void) /*{{{*/ { switch_to_window (Save_Window); } /*}}}*/ void jed_set_default_mouse_hook (char *hook_name, char *function) /*{{{*/ { SLang_Name_Type *f; f = SLang_get_function (function); if (!strcmp ("mouse_drag", hook_name)) Jed_Default_Mouse_Drag_Hook = f; else if (!strcmp ("mouse_up", hook_name)) Jed_Default_Mouse_Up_Hook = f; else if (!strcmp ("mouse_down", hook_name)) Jed_Default_Mouse_Down_Hook = f; else if (!strcmp ("mouse_status_up", hook_name)) Jed_Mouse_Status_Up_Hook = f; else if (!strcmp ("mouse_status_down", hook_name)) Jed_Mouse_Status_Down_Hook = f; else if (!strcmp ("mouse_status_drag", hook_name)) Jed_Mouse_Status_Drag_Hook = f; else if (!strcmp ("mouse_status_drag", hook_name)) Jed_Mouse_Status_Drag_Hook = f; #if JED_HAS_MULTICLICK else if (!strcmp ("mouse_2click", hook_name)) Jed_Default_Mouse_2Click_Hook = f; else if (!strcmp ("mouse_3click", hook_name)) Jed_Default_Mouse_3Click_Hook = f; #endif } /*}}}*/