| File: | src/lib/libmenu/m_driver.c |
| Warning: | line 545, column 11 Access to field 'y' results in a dereference of a null pointer (loaded from variable 'item') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: m_driver.c,v 1.8 2010/01/12 23:22:07 nicm Exp $ */ | |||
| 2 | ||||
| 3 | /**************************************************************************** | |||
| 4 | * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * | |||
| 5 | * * | |||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a * | |||
| 7 | * copy of this software and associated documentation files (the * | |||
| 8 | * "Software"), to deal in the Software without restriction, including * | |||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, * | |||
| 10 | * distribute, distribute with modifications, sublicense, and/or sell * | |||
| 11 | * copies of the Software, and to permit persons to whom the Software is * | |||
| 12 | * furnished to do so, subject to the following conditions: * | |||
| 13 | * * | |||
| 14 | * The above copyright notice and this permission notice shall be included * | |||
| 15 | * in all copies or substantial portions of the Software. * | |||
| 16 | * * | |||
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * | |||
| 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * | |||
| 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * | |||
| 20 | * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * | |||
| 21 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * | |||
| 22 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * | |||
| 23 | * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * | |||
| 24 | * * | |||
| 25 | * Except as contained in this notice, the name(s) of the above copyright * | |||
| 26 | * holders shall not be used in advertising or otherwise to promote the * | |||
| 27 | * sale, use or other dealings in this Software without prior written * | |||
| 28 | * authorization. * | |||
| 29 | ****************************************************************************/ | |||
| 30 | ||||
| 31 | /**************************************************************************** | |||
| 32 | * Author: Juergen Pfeifer, 1995,1997 * | |||
| 33 | ****************************************************************************/ | |||
| 34 | ||||
| 35 | /*************************************************************************** | |||
| 36 | * Module m_driver * | |||
| 37 | * Central dispatching routine * | |||
| 38 | ***************************************************************************/ | |||
| 39 | ||||
| 40 | #include "menu.priv.h" | |||
| 41 | ||||
| 42 | MODULE_ID("$Id: m_driver.c,v 1.8 2010/01/12 23:22:07 nicm Exp $") | |||
| 43 | ||||
| 44 | /* Macros */ | |||
| 45 | ||||
| 46 | /* Remove the last character from the match pattern buffer */ | |||
| 47 | #define Remove_Character_From_Pattern(menu)(menu)->pattern[--((menu)->pindex)] = '\0' \ | |||
| 48 | (menu)->pattern[--((menu)->pindex)] = '\0' | |||
| 49 | ||||
| 50 | /* Add a new character to the match pattern buffer */ | |||
| 51 | #define Add_Character_To_Pattern(menu,ch){ (menu)->pattern[((menu)->pindex)++] = (ch); (menu)-> pattern[(menu)->pindex] = '\0'; } \ | |||
| 52 | { (menu)->pattern[((menu)->pindex)++] = (ch);\ | |||
| 53 | (menu)->pattern[(menu)->pindex] = '\0'; } | |||
| 54 | ||||
| 55 | /*--------------------------------------------------------------------------- | |||
| 56 | | Facility : libnmenu | |||
| 57 | | Function : static bool Is_Sub_String( | |||
| 58 | | bool IgnoreCaseFlag, | |||
| 59 | | const char *part, | |||
| 60 | | const char *string) | |||
| 61 | | | |||
| 62 | | Description : Checks whether or not part is a substring of string. | |||
| 63 | | | |||
| 64 | | Return Values : TRUE - if it is a substring | |||
| 65 | | FALSE - if it is not a substring | |||
| 66 | +--------------------------------------------------------------------------*/ | |||
| 67 | static bool_Bool | |||
| 68 | Is_Sub_String( | |||
| 69 | bool_Bool IgnoreCaseFlag, | |||
| 70 | const char *part, | |||
| 71 | const char *string | |||
| 72 | ) | |||
| 73 | { | |||
| 74 | assert(part && string)((void)0); | |||
| 75 | if (IgnoreCaseFlag) | |||
| 76 | { | |||
| 77 | while (*string && *part) | |||
| 78 | { | |||
| 79 | if (toupper(UChar(*string++)((unsigned char)(*string++))) != toupper(UChar(*part)((unsigned char)(*part)))) | |||
| 80 | break; | |||
| 81 | part++; | |||
| 82 | } | |||
| 83 | } | |||
| 84 | else | |||
| 85 | { | |||
| 86 | while (*string && *part) | |||
| 87 | if (*part != *string++) | |||
| 88 | break; | |||
| 89 | part++; | |||
| 90 | } | |||
| 91 | return ((*part) ? FALSE0 : TRUE1); | |||
| 92 | } | |||
| 93 | ||||
| 94 | /*--------------------------------------------------------------------------- | |||
| 95 | | Facility : libnmenu | |||
| 96 | | Function : int _nc_Match_Next_Character_In_Item_Name( | |||
| 97 | | MENU *menu, | |||
| 98 | | int ch, | |||
| 99 | | ITEM **item) | |||
| 100 | | | |||
| 101 | | Description : This internal routine is called for a menu positioned | |||
| 102 | | at an item with three different classes of characters: | |||
| 103 | | - a printable character; the character is added to | |||
| 104 | | the current pattern and the next item matching | |||
| 105 | | this pattern is searched. | |||
| 106 | | - NUL; the pattern stays as it is and the next item | |||
| 107 | | matching the pattern is searched | |||
| 108 | | - BS; the pattern stays as it is and the previous | |||
| 109 | | item matching the pattern is searched | |||
| 110 | | | |||
| 111 | | The item parameter contains on call a pointer to | |||
| 112 | | the item where the search starts. On return - if | |||
| 113 | | a match was found - it contains a pointer to the | |||
| 114 | | matching item. | |||
| 115 | | | |||
| 116 | | Return Values : E_OK - an item matching the pattern was found | |||
| 117 | | E_NO_MATCH - nothing found | |||
| 118 | +--------------------------------------------------------------------------*/ | |||
| 119 | NCURSES_EXPORT(int)int | |||
| 120 | _nc_Match_Next_Character_In_Item_Name | |||
| 121 | (MENU * menu, int ch, ITEM ** item) | |||
| 122 | { | |||
| 123 | bool_Bool found = FALSE0, passed = FALSE0; | |||
| 124 | int idx, last; | |||
| 125 | ||||
| 126 | T((T_CALLED("_nc_Match_Next_Character(%p,%d,%p)"), menu, ch, item)); | |||
| 127 | ||||
| 128 | assert(menu && item && *item)((void)0); | |||
| 129 | idx = (*item)->index; | |||
| 130 | ||||
| 131 | if (ch && ch != BS(8)) | |||
| 132 | { | |||
| 133 | /* if we become to long, we need no further checking : there can't be | |||
| 134 | a match ! */ | |||
| 135 | if ((menu->pindex + 1) > menu->namelen) | |||
| 136 | RETURN(E_NO_MATCH)return( ((*__errno())=((-9))) ); | |||
| 137 | ||||
| 138 | Add_Character_To_Pattern(menu, ch){ (menu)->pattern[((menu)->pindex)++] = (ch); (menu)-> pattern[(menu)->pindex] = '\0'; }; | |||
| 139 | /* we artificially position one item back, because in the do...while | |||
| 140 | loop we start with the next item. This means, that with a new | |||
| 141 | pattern search we always start the scan with the actual item. If | |||
| 142 | we do a NEXT_PATTERN oder PREV_PATTERN search, we start with the | |||
| 143 | one after or before the actual item. */ | |||
| 144 | if (--idx < 0) | |||
| 145 | idx = menu->nitems - 1; | |||
| 146 | } | |||
| 147 | ||||
| 148 | last = idx; /* this closes the cycle */ | |||
| 149 | ||||
| 150 | do | |||
| 151 | { | |||
| 152 | if (ch == BS(8)) | |||
| 153 | { /* we have to go backward */ | |||
| 154 | if (--idx < 0) | |||
| 155 | idx = menu->nitems - 1; | |||
| 156 | } | |||
| 157 | else | |||
| 158 | { /* otherwise we always go forward */ | |||
| 159 | if (++idx >= menu->nitems) | |||
| 160 | idx = 0; | |||
| 161 | } | |||
| 162 | if (Is_Sub_String((bool_Bool)((menu->opt & O_IGNORECASE(0x08)) != 0), | |||
| 163 | menu->pattern, | |||
| 164 | menu->items[idx]->name.str) | |||
| 165 | ) | |||
| 166 | found = TRUE1; | |||
| 167 | else | |||
| 168 | passed = TRUE1; | |||
| 169 | } | |||
| 170 | while (!found && (idx != last)); | |||
| 171 | ||||
| 172 | if (found) | |||
| 173 | { | |||
| 174 | if (!((idx == (*item)->index) && passed)) | |||
| 175 | { | |||
| 176 | *item = menu->items[idx]; | |||
| 177 | RETURN(E_OK)return( ((*__errno())=((0))) ); | |||
| 178 | } | |||
| 179 | /* This point is reached, if we fully cycled through the item list | |||
| 180 | and the only match we found is the starting item. With a NEXT_PATTERN | |||
| 181 | or PREV_PATTERN scan this means, that there was no additional match. | |||
| 182 | If we searched with an expanded new pattern, we should never reach | |||
| 183 | this point, because if the expanded pattern matches also the actual | |||
| 184 | item we will find it in the first attempt (passed==FALSE) and we | |||
| 185 | will never cycle through the whole item array. | |||
| 186 | */ | |||
| 187 | assert(ch == 0 || ch == BS)((void)0); | |||
| 188 | } | |||
| 189 | else | |||
| 190 | { | |||
| 191 | if (ch && ch != BS(8) && menu->pindex > 0) | |||
| 192 | { | |||
| 193 | /* if we had no match with a new pattern, we have to restore it */ | |||
| 194 | Remove_Character_From_Pattern(menu)(menu)->pattern[--((menu)->pindex)] = '\0'; | |||
| 195 | } | |||
| 196 | } | |||
| 197 | RETURN(E_NO_MATCH)return( ((*__errno())=((-9))) ); | |||
| 198 | } | |||
| 199 | ||||
| 200 | /*--------------------------------------------------------------------------- | |||
| 201 | | Facility : libnmenu | |||
| 202 | | Function : int menu_driver(MENU *menu, int c) | |||
| 203 | | | |||
| 204 | | Description : Central dispatcher for the menu. Translates the logical | |||
| 205 | | request 'c' into a menu action. | |||
| 206 | | | |||
| 207 | | Return Values : E_OK - success | |||
| 208 | | E_BAD_ARGUMENT - invalid menu pointer | |||
| 209 | | E_BAD_STATE - menu is in user hook routine | |||
| 210 | | E_NOT_POSTED - menu is not posted | |||
| 211 | +--------------------------------------------------------------------------*/ | |||
| 212 | NCURSES_EXPORT(int)int | |||
| 213 | menu_driver(MENU * menu, int c) | |||
| 214 | { | |||
| 215 | #define NAVIGATE(dir)if (!item->dir) result = (-12); else item = item->dir \ | |||
| 216 | if (!item->dir)\ | |||
| 217 | result = E_REQUEST_DENIED(-12);\ | |||
| 218 | else\ | |||
| 219 | item = item->dir | |||
| 220 | ||||
| 221 | int result = E_OK(0); | |||
| 222 | ITEM *item; | |||
| 223 | int my_top_row, rdiff; | |||
| 224 | ||||
| 225 | T((T_CALLED("menu_driver(%p,%d)"), menu, c)); | |||
| 226 | ||||
| 227 | if (!menu) | |||
| ||||
| 228 | RETURN(E_BAD_ARGUMENT)return( ((*__errno())=((-2))) ); | |||
| 229 | ||||
| 230 | if (menu->status & _IN_DRIVER(0x02U)) | |||
| 231 | RETURN(E_BAD_STATE)return( ((*__errno())=((-5))) ); | |||
| 232 | if (!(menu->status & _POSTED(0x01U))) | |||
| 233 | RETURN(E_NOT_POSTED)return( ((*__errno())=((-7))) ); | |||
| 234 | ||||
| 235 | item = menu->curitem; | |||
| 236 | ||||
| 237 | my_top_row = menu->toprow; | |||
| 238 | assert(item)((void)0); | |||
| 239 | ||||
| 240 | if ((c > KEY_MAX0777) && (c <= MAX_MENU_COMMAND(0777 + 17))) | |||
| 241 | { | |||
| 242 | if (!((c == REQ_BACK_PATTERN(0777 + 15)) | |||
| 243 | || (c == REQ_NEXT_MATCH(0777 + 16)) || (c == REQ_PREV_MATCH(0777 + 17)))) | |||
| 244 | { | |||
| 245 | assert(menu->pattern)((void)0); | |||
| 246 | Reset_Pattern(menu){ (menu)->pindex = 0; (menu)->pattern[0] = '\0'; }; | |||
| 247 | } | |||
| 248 | ||||
| 249 | switch (c) | |||
| 250 | { | |||
| 251 | case REQ_LEFT_ITEM(0777 + 1): | |||
| 252 | /*=================*/ | |||
| 253 | NAVIGATE(left)if (!item->left) result = (-12); else item = item->left; | |||
| 254 | break; | |||
| 255 | ||||
| 256 | case REQ_RIGHT_ITEM(0777 + 2): | |||
| 257 | /*==================*/ | |||
| 258 | NAVIGATE(right)if (!item->right) result = (-12); else item = item->right; | |||
| 259 | break; | |||
| 260 | ||||
| 261 | case REQ_UP_ITEM(0777 + 3): | |||
| 262 | /*===============*/ | |||
| 263 | NAVIGATE(up)if (!item->up) result = (-12); else item = item->up; | |||
| 264 | break; | |||
| 265 | ||||
| 266 | case REQ_DOWN_ITEM(0777 + 4): | |||
| 267 | /*=================*/ | |||
| 268 | NAVIGATE(down)if (!item->down) result = (-12); else item = item->down; | |||
| 269 | break; | |||
| 270 | ||||
| 271 | case REQ_SCR_ULINE(0777 + 5): | |||
| 272 | /*=================*/ | |||
| 273 | if (my_top_row == 0 || !(item->up)) | |||
| 274 | result = E_REQUEST_DENIED(-12); | |||
| 275 | else | |||
| 276 | { | |||
| 277 | --my_top_row; | |||
| 278 | item = item->up; | |||
| 279 | } | |||
| 280 | break; | |||
| 281 | ||||
| 282 | case REQ_SCR_DLINE(0777 + 6): | |||
| 283 | /*=================*/ | |||
| 284 | if ((my_top_row + menu->arows >= menu->rows) || !(item->down)) | |||
| 285 | { | |||
| 286 | /* only if the menu has less items than rows, we can deny the | |||
| 287 | request. Otherwise the epilogue of this routine adjusts the | |||
| 288 | top row if necessary */ | |||
| 289 | result = E_REQUEST_DENIED(-12); | |||
| 290 | } | |||
| 291 | else | |||
| 292 | { | |||
| 293 | my_top_row++; | |||
| 294 | item = item->down; | |||
| 295 | } | |||
| 296 | break; | |||
| 297 | ||||
| 298 | case REQ_SCR_DPAGE(0777 + 7): | |||
| 299 | /*=================*/ | |||
| 300 | rdiff = menu->rows - (menu->arows + my_top_row); | |||
| 301 | if (rdiff > menu->arows) | |||
| 302 | rdiff = menu->arows; | |||
| 303 | if (rdiff <= 0) | |||
| 304 | result = E_REQUEST_DENIED(-12); | |||
| 305 | else | |||
| 306 | { | |||
| 307 | my_top_row += rdiff; | |||
| 308 | while (rdiff-- > 0 && item != 0 && item->down != 0) | |||
| 309 | item = item->down; | |||
| 310 | } | |||
| 311 | break; | |||
| 312 | ||||
| 313 | case REQ_SCR_UPAGE(0777 + 8): | |||
| 314 | /*=================*/ | |||
| 315 | rdiff = (menu->arows < my_top_row) ? menu->arows : my_top_row; | |||
| 316 | if (rdiff <= 0) | |||
| 317 | result = E_REQUEST_DENIED(-12); | |||
| 318 | else | |||
| 319 | { | |||
| 320 | my_top_row -= rdiff; | |||
| 321 | while (rdiff-- > 0 && item != 0 && item->up != 0) | |||
| 322 | item = item->up; | |||
| 323 | } | |||
| 324 | break; | |||
| 325 | ||||
| 326 | case REQ_FIRST_ITEM(0777 + 9): | |||
| 327 | /*==================*/ | |||
| 328 | item = menu->items[0]; | |||
| 329 | break; | |||
| 330 | ||||
| 331 | case REQ_LAST_ITEM(0777 + 10): | |||
| 332 | /*=================*/ | |||
| 333 | item = menu->items[menu->nitems - 1]; | |||
| 334 | break; | |||
| 335 | ||||
| 336 | case REQ_NEXT_ITEM(0777 + 11): | |||
| 337 | /*=================*/ | |||
| 338 | if ((item->index + 1) >= menu->nitems) | |||
| 339 | { | |||
| 340 | if (menu->opt & O_NONCYCLIC(0x20)) | |||
| 341 | result = E_REQUEST_DENIED(-12); | |||
| 342 | else | |||
| 343 | item = menu->items[0]; | |||
| 344 | } | |||
| 345 | else | |||
| 346 | item = menu->items[item->index + 1]; | |||
| 347 | break; | |||
| 348 | ||||
| 349 | case REQ_PREV_ITEM(0777 + 12): | |||
| 350 | /*=================*/ | |||
| 351 | if (item->index <= 0) | |||
| 352 | { | |||
| 353 | if (menu->opt & O_NONCYCLIC(0x20)) | |||
| 354 | result = E_REQUEST_DENIED(-12); | |||
| 355 | else | |||
| 356 | item = menu->items[menu->nitems - 1]; | |||
| 357 | } | |||
| 358 | else | |||
| 359 | item = menu->items[item->index - 1]; | |||
| 360 | break; | |||
| 361 | ||||
| 362 | case REQ_TOGGLE_ITEM(0777 + 13): | |||
| 363 | /*===================*/ | |||
| 364 | if (menu->opt & O_ONEVALUE(0x01)) | |||
| 365 | { | |||
| 366 | result = E_REQUEST_DENIED(-12); | |||
| 367 | } | |||
| 368 | else | |||
| 369 | { | |||
| 370 | if (menu->curitem->opt & O_SELECTABLE(0x01)) | |||
| 371 | { | |||
| 372 | menu->curitem->value = !menu->curitem->value; | |||
| 373 | Move_And_Post_Item(menu, menu->curitem){wmove((menu)->win,(menu)->spc_rows*(menu->curitem)-> y,((menu)->itemlen+(menu)->spc_cols)*(menu->curitem) ->x); _nc_Post_Item((menu),(menu->curitem));}; | |||
| 374 | _nc_Show_Menu(menu); | |||
| 375 | } | |||
| 376 | else | |||
| 377 | result = E_NOT_SELECTABLE(-10); | |||
| 378 | } | |||
| 379 | break; | |||
| 380 | ||||
| 381 | case REQ_CLEAR_PATTERN(0777 + 14): | |||
| 382 | /*=====================*/ | |||
| 383 | /* already cleared in prologue */ | |||
| 384 | break; | |||
| 385 | ||||
| 386 | case REQ_BACK_PATTERN(0777 + 15): | |||
| 387 | /*====================*/ | |||
| 388 | if (menu->pindex > 0) | |||
| 389 | { | |||
| 390 | assert(menu->pattern)((void)0); | |||
| 391 | Remove_Character_From_Pattern(menu)(menu)->pattern[--((menu)->pindex)] = '\0'; | |||
| 392 | pos_menu_cursor(menu); | |||
| 393 | } | |||
| 394 | else | |||
| 395 | result = E_REQUEST_DENIED(-12); | |||
| 396 | break; | |||
| 397 | ||||
| 398 | case REQ_NEXT_MATCH(0777 + 16): | |||
| 399 | /*==================*/ | |||
| 400 | assert(menu->pattern)((void)0); | |||
| 401 | if (menu->pattern[0]) | |||
| 402 | result = _nc_Match_Next_Character_In_Item_Name(menu, 0, &item); | |||
| 403 | else | |||
| 404 | { | |||
| 405 | if ((item->index + 1) < menu->nitems) | |||
| 406 | item = menu->items[item->index + 1]; | |||
| 407 | else | |||
| 408 | { | |||
| 409 | if (menu->opt & O_NONCYCLIC(0x20)) | |||
| 410 | result = E_REQUEST_DENIED(-12); | |||
| 411 | else | |||
| 412 | item = menu->items[0]; | |||
| 413 | } | |||
| 414 | } | |||
| 415 | break; | |||
| 416 | ||||
| 417 | case REQ_PREV_MATCH(0777 + 17): | |||
| 418 | /*==================*/ | |||
| 419 | assert(menu->pattern)((void)0); | |||
| 420 | if (menu->pattern[0]) | |||
| 421 | result = _nc_Match_Next_Character_In_Item_Name(menu, BS(8), &item); | |||
| 422 | else | |||
| 423 | { | |||
| 424 | if (item->index) | |||
| 425 | item = menu->items[item->index - 1]; | |||
| 426 | else | |||
| 427 | { | |||
| 428 | if (menu->opt & O_NONCYCLIC(0x20)) | |||
| 429 | result = E_REQUEST_DENIED(-12); | |||
| 430 | else | |||
| 431 | item = menu->items[menu->nitems - 1]; | |||
| 432 | } | |||
| 433 | } | |||
| 434 | break; | |||
| 435 | ||||
| 436 | default: | |||
| 437 | /*======*/ | |||
| 438 | result = E_UNKNOWN_COMMAND(-8); | |||
| 439 | break; | |||
| 440 | } | |||
| 441 | } | |||
| 442 | else | |||
| 443 | { /* not a command */ | |||
| 444 | if (!(c & ~((int)MAX_REGULAR_CHARACTER(0xff))) && isprint(UChar(c)((unsigned char)(c)))) | |||
| 445 | result = _nc_Match_Next_Character_In_Item_Name(menu, c, &item); | |||
| 446 | #ifdef NCURSES_MOUSE_VERSION1 | |||
| 447 | else if (KEY_MOUSE0631 == c) | |||
| 448 | { | |||
| 449 | MEVENT event; | |||
| 450 | WINDOW *uwin = Get_Menu_UserWin(menu)((menu)->userwin ? (menu)->userwin : stdscr); | |||
| 451 | ||||
| 452 | getmouse(&event); | |||
| 453 | if ((event.bstate & (BUTTON1_CLICKED((004L) << (((1) - 1) * 6)) | | |||
| 454 | BUTTON1_DOUBLE_CLICKED((010L) << (((1) - 1) * 6)) | | |||
| 455 | BUTTON1_TRIPLE_CLICKED((020L) << (((1) - 1) * 6)))) | |||
| 456 | && wenclose(uwin, event.y, event.x)) | |||
| 457 | { /* we react only if the click was in the userwin, that means | |||
| 458 | * inside the menu display area or at the decoration window. | |||
| 459 | */ | |||
| 460 | WINDOW *sub = Get_Menu_Window(menu)((menu)->usersub ? (menu)->usersub : ((menu)->userwin ? (menu)->userwin : stdscr)); | |||
| 461 | int ry = event.y, rx = event.x; /* screen coordinates */ | |||
| 462 | ||||
| 463 | result = E_REQUEST_DENIED(-12); | |||
| 464 | if (mouse_trafo(&ry, &rx, FALSE)wmouse_trafo(stdscr,&ry,&rx,0)) | |||
| 465 | { /* rx, ry are now "curses" coordinates */ | |||
| 466 | if (ry < sub->_begy) | |||
| 467 | { /* we clicked above the display region; this is | |||
| 468 | * interpreted as "scroll up" request | |||
| 469 | */ | |||
| 470 | if (event.bstate & BUTTON1_CLICKED((004L) << (((1) - 1) * 6))) | |||
| 471 | result = menu_driver(menu, REQ_SCR_ULINE(0777 + 5)); | |||
| 472 | else if (event.bstate & BUTTON1_DOUBLE_CLICKED((010L) << (((1) - 1) * 6))) | |||
| 473 | result = menu_driver(menu, REQ_SCR_UPAGE(0777 + 8)); | |||
| 474 | else if (event.bstate & BUTTON1_TRIPLE_CLICKED((020L) << (((1) - 1) * 6))) | |||
| 475 | result = menu_driver(menu, REQ_FIRST_ITEM(0777 + 9)); | |||
| 476 | RETURN(result)return( ((*__errno())=(result)) ); | |||
| 477 | } | |||
| 478 | else if (ry > sub->_begy + sub->_maxy) | |||
| 479 | { /* we clicked below the display region; this is | |||
| 480 | * interpreted as "scroll down" request | |||
| 481 | */ | |||
| 482 | if (event.bstate & BUTTON1_CLICKED((004L) << (((1) - 1) * 6))) | |||
| 483 | result = menu_driver(menu, REQ_SCR_DLINE(0777 + 6)); | |||
| 484 | else if (event.bstate & BUTTON1_DOUBLE_CLICKED((010L) << (((1) - 1) * 6))) | |||
| 485 | result = menu_driver(menu, REQ_SCR_DPAGE(0777 + 7)); | |||
| 486 | else if (event.bstate & BUTTON1_TRIPLE_CLICKED((020L) << (((1) - 1) * 6))) | |||
| 487 | result = menu_driver(menu, REQ_LAST_ITEM(0777 + 10)); | |||
| 488 | RETURN(result)return( ((*__errno())=(result)) ); | |||
| 489 | } | |||
| 490 | else if (wenclose(sub, event.y, event.x)) | |||
| 491 | { /* Inside the area we try to find the hit item */ | |||
| 492 | int i, x, y, err; | |||
| 493 | ||||
| 494 | ry = event.y; | |||
| 495 | rx = event.x; | |||
| 496 | if (wmouse_trafo(sub, &ry, &rx, FALSE0)) | |||
| 497 | { | |||
| 498 | for (i = 0; i < menu->nitems; i++) | |||
| 499 | { | |||
| 500 | err = _nc_menu_cursor_pos(menu, menu->items[i], | |||
| 501 | &y, &x); | |||
| 502 | if (E_OK(0) == err) | |||
| 503 | { | |||
| 504 | if ((ry == y) && | |||
| 505 | (rx >= x) && | |||
| 506 | (rx < x + menu->itemlen)) | |||
| 507 | { | |||
| 508 | item = menu->items[i]; | |||
| 509 | result = E_OK(0); | |||
| 510 | break; | |||
| 511 | } | |||
| 512 | } | |||
| 513 | } | |||
| 514 | if (E_OK(0) == result) | |||
| 515 | { /* We found an item, now we can handle the click. | |||
| 516 | * A single click just positions the menu cursor | |||
| 517 | * to the clicked item. A double click toggles | |||
| 518 | * the item. | |||
| 519 | */ | |||
| 520 | if (event.bstate & BUTTON1_DOUBLE_CLICKED((010L) << (((1) - 1) * 6))) | |||
| 521 | { | |||
| 522 | _nc_New_TopRow_and_CurrentItem(menu, | |||
| 523 | my_top_row, | |||
| 524 | item); | |||
| 525 | menu_driver(menu, REQ_TOGGLE_ITEM(0777 + 13)); | |||
| 526 | result = E_UNKNOWN_COMMAND(-8); | |||
| 527 | } | |||
| 528 | } | |||
| 529 | } | |||
| 530 | } | |||
| 531 | } | |||
| 532 | } | |||
| 533 | else | |||
| 534 | result = E_REQUEST_DENIED(-12); | |||
| 535 | } | |||
| 536 | #endif /* NCURSES_MOUSE_VERSION */ | |||
| 537 | else | |||
| 538 | result = E_UNKNOWN_COMMAND(-8); | |||
| 539 | } | |||
| 540 | ||||
| 541 | if (E_OK(0) == result
| |||
| 542 | { | |||
| 543 | /* Adjust the top row if it turns out that the current item unfortunately | |||
| 544 | doesn't appear in the menu window */ | |||
| 545 | if (item->y < my_top_row) | |||
| ||||
| 546 | my_top_row = item->y; | |||
| 547 | else if (item->y >= (my_top_row + menu->arows)) | |||
| 548 | my_top_row = item->y - menu->arows + 1; | |||
| 549 | ||||
| 550 | _nc_New_TopRow_and_CurrentItem(menu, my_top_row, item); | |||
| 551 | ||||
| 552 | } | |||
| 553 | ||||
| 554 | RETURN(result)return( ((*__errno())=(result)) ); | |||
| 555 | } | |||
| 556 | ||||
| 557 | /* m_driver.c ends here */ |