* New version 2.26
[alpine.git] / pico / osdep / mouse.c
blobdbcd5cd93bb50fa26a7b9c84f2cc7b43c3784fec
1 /*
2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2022 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
15 #include <system.h>
16 #include <general.h>
18 #include "../headers.h"
20 #include "getkey.h"
22 #ifdef _WINDOWS
23 #include "mswin.h"
24 #endif
26 #include "mouse.h"
28 #ifdef MOUSE
31 #ifndef _WINDOWS
33 /* useful definitions */
34 #define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */
35 #define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */
38 /* useful declarations */
39 static int mexist = 0; /* is the mouse driver installed? */
40 static unsigned mnoop;
44 /* internal prototypes */
45 void mouseon(void);
46 void mouseoff(void);
50 /*
51 * init_mouse - check for xterm and initialize mouse tracking if present...
53 int
54 init_mouse(void)
56 if(mexist)
57 return(TRUE);
59 if(getenv("DISPLAY")){
60 mouseon();
61 kpinsert("\033[M", KEY_XTERM_MOUSE, 1);
62 return(mexist = TRUE);
64 else
65 return(FALSE);
69 /*
70 * end_mouse - clear xterm mouse tracking if present...
72 void
73 end_mouse(void)
75 if(mexist){
76 mexist = 0; /* just see if it exists here. */
77 mouseoff();
83 * mouseexist - function to let outsiders know if mouse is turned on
84 * or not.
86 int
87 mouseexist(void)
89 return(mexist);
94 * mouseon - call made available for programs calling pico to turn ON the
95 * mouse cursor.
97 void
98 mouseon(void)
100 fputs(XTERM_MOUSE_ON, stdout);
105 * mouseon - call made available for programs calling pico to turn OFF the
106 * mouse cursor.
108 void
109 mouseoff(void)
111 fputs(XTERM_MOUSE_OFF, stdout);
116 * checkmouse - look for mouse events in key menu and return
117 * appropriate value.
120 checkmouse(unsigned long *ch, int down, int mcol, int mrow)
122 static int oindex;
123 int i = 0, rv = 0;
124 MENUITEM *mp;
126 if(!mexist || mcol < 0 || mrow < 0)
127 return(FALSE);
129 if(down) /* button down */
130 oindex = -1;
132 for(mp = mfunc; mp; mp = mp->next)
133 if(mp->action && M_ACTIVE(mrow, mcol, mp))
134 break;
136 if(mp){
137 unsigned long r;
139 r = (*mp->action)(down ? M_EVENT_DOWN : M_EVENT_UP,
140 mrow, mcol, M_BUTTON_LEFT, 0);
141 if(r){
142 *ch = r;
143 rv = TRUE;
146 else{
147 while(1){ /* see if we understand event */
148 if(i >= 12){
149 i = -1;
150 break;
153 if(M_ACTIVE(mrow, mcol, &menuitems[i]))
154 break;
156 i++;
159 if(down){ /* button down */
160 oindex = i; /* remember where */
161 if(i != -1
162 && menuitems[i].label_hiliter != NULL
163 && menuitems[i].val != mnoop) /* invert label */
164 (*menuitems[i].label_hiliter)(1, &menuitems[i]);
166 else{ /* button up */
167 if(oindex != -1){
168 if(i == oindex){
169 *ch = menuitems[i].val;
170 rv = TRUE;
176 /* restore label */
177 if(!down
178 && oindex != -1
179 && menuitems[oindex].label_hiliter != NULL
180 && menuitems[oindex].val != mnoop)
181 (*menuitems[oindex].label_hiliter)(0, &menuitems[oindex]);
183 return(rv);
188 * invert_label - highlight the label of the given menu item.
190 void
191 invert_label(int state, MENUITEM *m)
193 unsigned i, j;
194 int col_offset, savettrow, savettcol;
195 char *lp;
197 get_cursor(&savettrow, &savettcol);
200 * Leave the command name bold
202 col_offset = (state || !(lp=strchr(m->label, ' '))) ? 0 : (lp - m->label);
203 movecursor((int)m->tl.r, (int)m->tl.c + col_offset);
204 flip_inv(state);
206 for(i = m->tl.r; i <= m->br.r; i++)
207 for(j = m->tl.c + col_offset; j <= m->br.c; j++)
208 if(i == m->lbl.r && j == m->lbl.c + col_offset && m->label){
209 lp = m->label + col_offset; /* show label?? */
210 while(*lp && j++ < m->br.c)
211 putc(*lp++, stdout);
213 continue;
215 else
216 putc(' ', stdout);
218 if(state)
219 flip_inv(FALSE);
221 movecursor(savettrow, savettcol);
224 #else /* _WINDOWS */
226 #define MOUSE_BUTTONS 3
228 static int mexist = 0; /* is the mouse driver installed? */
229 static int nbuttons; /* number of buttons on the mouse */
230 static unsigned mnoop;
233 * init_mouse - check for and initialize mouse driver...
237 init_mouse(void)
239 nbuttons = MOUSE_BUTTONS;
240 return (mexist = TRUE); /* Mouse always exists under windows */
244 * end_mouse - a no-op on Windows
246 void
247 end_mouse(void)
252 * mouseexist - function to let outsiders know if mouse is turned on
253 * or not.
256 mouseexist(void)
258 return(mexist);
262 * checkmouse - Check mouse and return mapped command.
264 * EXPORTED to pico.
265 * NOTE: "down", "xxx", and "yyy" aren't used under windows.
267 int
268 checkmouse (unsigned long *ch, int ddd, int xxx, int yyy)
270 static int oindex; /* Index of previous mouse down. */
271 int mcol; /* current mouse column */
272 int mrow; /* current mouse row */
273 unsigned long r;
274 int rv = 0; /* TRUE when we have something to return. */
275 MEvent mouse;
276 int i = 0;
277 MENUITEM *mp;
280 *ch = 0;
282 /* Mouse installed? */
283 if (!mexist)
284 return (FALSE);
286 if (!mswin_getmouseevent (&mouse))
287 return (FALSE);
290 /* Location of mouse event. */
291 mcol = mouse.nColumn;
292 mrow = mouse.nRow;
297 * If there is a tracking function it gets all the mouse events
298 * regardless of where they occur.
300 if (mtrack != NULL) {
301 r = mtrack (mouse.event, mrow, mcol, mouse.button, mouse.keys);
302 if (r & 0xffff){
303 *ch = r;
304 rv = TRUE;
306 return (rv);
312 /* Mouse down or up? */
313 if (mouse.event == M_EVENT_DOWN) { /* button down */
314 oindex = -1; /* No Previous mouse down. */
318 /* In special screen region? */
319 for(mp = mfunc; mp; mp = mp->next)
320 if(mp->action && M_ACTIVE(mrow, mcol, mp))
321 break;
323 if(mp){
325 r = (*mp->action)(mouse.event, mrow, mcol, mouse.button, mouse.keys);
326 if (r){
327 *ch = r;
328 rv = TRUE;
331 else if(mouse.button == M_BUTTON_LEFT){
333 /* In any of the menuitems? */
334 while(1){ /* see if we understand event */
335 if(i >= 12){
336 i = -1; /* Not Found. */
337 break;
340 if(M_ACTIVE(mrow, mcol, &menuitems[i]))
341 break; /* Found. */
343 i++; /* Next. */
346 /* Now, was that a mouse down or mouse up? */
347 if (mouse.event == M_EVENT_DOWN) { /* button down */
348 oindex = i; /* remember where */
349 if(i != -1){ /* invert label */
350 if(menuitems[i].label_hiliter != NULL)
351 (*menuitems[i].label_hiliter)(1, &menuitems[i]);
352 else
353 invert_label(1, &menuitems[i]);
356 else if (mouse.event == M_EVENT_UP) {/* button up */
357 if (oindex != -1) { /* If up in menu item. */
358 if (i == oindex){ /* And same item down in. */
359 *ch = menuitems[i].val; /* Return menu character. */
360 rv = 1;
365 else if(mouse.button == M_BUTTON_RIGHT){
366 if (mouse.event == M_EVENT_UP) {
367 mswin_keymenu_popup();
371 /* If this is mouse up AND there was a mouse down in a menu item
372 * then uninvert that menu item */
373 if(mouse.event == M_EVENT_UP && oindex != -1){
374 if(menuitems[oindex].label_hiliter != NULL)
375 (*menuitems[oindex].label_hiliter)(0, &menuitems[oindex]);
376 else
377 invert_label(0, &menuitems[oindex]);
380 return(rv);
384 * invert_label - highlight the label of the given menu item.
386 void
387 invert_label(int state, MENUITEM *m)
389 int r, c;
390 unsigned i, j;
391 char *lp;
392 int old_state;
393 int wasShown;
394 int col_offset;
395 COLOR_PAIR *lastc = NULL;
396 if(m->val == mnoop)
397 return;
400 mswin_getpos (&r, &c); /* get cursor position */
401 wasShown = mswin_showcaret (0);
402 old_state = mswin_getrevstate ();
404 * Leave the command name bold
406 col_offset = (state || !(lp=strchr(m->label, ' '))) ? 0 : (lp - m->label);
407 (*term.t_move)(m->tl.r, m->tl.c + col_offset);
408 if(state && m->kncp)
409 lastc = pico_set_colorp(m->kncp, PSC_REV|PSC_RET);
410 else if(!state && m->klcp)
411 lastc = pico_set_colorp(m->klcp, PSC_NORM|PSC_RET);
412 else
413 (*term.t_rev)(state);
415 for(i = m->tl.r; i <= m->br.r; i++) {
416 for(j = m->tl.c + col_offset; j <= m->br.c; j++) {
417 if(i == m->lbl.r && j == m->lbl.c + col_offset){ /* show label?? */
418 lp = m->label + col_offset;
419 while(*lp && j++ < m->br.c)
420 (*term.t_putchar)(*lp++);
422 continue;
424 else
425 (*term.t_putchar)(' ');
429 if(lastc){
430 (void)pico_set_colorp(lastc, PSC_NONE);
431 free_color_pair(&lastc);
433 else
434 (*term.t_rev)(old_state);
435 mswin_move (r, c);
436 mswin_showcaret (wasShown);
440 #endif /* _WINDOWS */
442 #endif /* MOUSE */