1/* $OpenBSD: m_post.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ 2 3/**************************************************************************** 4 * Copyright 2020-2021,2022 Thomas E. Dickey * 5 * Copyright 1998-2010,2012 Free Software Foundation, Inc. * 6 * * 7 * Permission is hereby granted, free of charge, to any person obtaining a * 8 * copy of this software and associated documentation files (the * 9 * "Software"), to deal in the Software without restriction, including * 10 * without limitation the rights to use, copy, modify, merge, publish, * 11 * distribute, distribute with modifications, sublicense, and/or sell * 12 * copies of the Software, and to permit persons to whom the Software is * 13 * furnished to do so, subject to the following conditions: * 14 * * 15 * The above copyright notice and this permission notice shall be included * 16 * in all copies or substantial portions of the Software. * 17 * * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 21 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 24 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 25 * * 26 * Except as contained in this notice, the name(s) of the above copyright * 27 * holders shall not be used in advertising or otherwise to promote the * 28 * sale, use or other dealings in this Software without prior written * 29 * authorization. * 30 ****************************************************************************/ 31 32/**************************************************************************** 33 * Author: Juergen Pfeifer, 1995,1997 * 34 ****************************************************************************/ 35 36/*************************************************************************** 37* Module m_post * 38* Write or erase menus from associated subwindows * 39***************************************************************************/ 40 41#include "menu.priv.h" 42 43MODULE_ID("$Id: m_post.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") 44 45/*--------------------------------------------------------------------------- 46| Facility : libnmenu 47| Function : void _nc_Post_Item(MENU *menu, ITEM *item) 48| 49| Description : Draw the item in the menus window at the current 50| window position 51| 52| Return Values : - 53+--------------------------------------------------------------------------*/ 54MENU_EXPORT(void) 55_nc_Post_Item(const MENU *menu, const ITEM *item) 56{ 57 int i; 58 chtype ch; 59 int item_x, item_y; 60 int count = 0; 61 bool isfore = FALSE, isback = FALSE, isgrey = FALSE; 62 int name_len; 63 64 assert(menu->win); 65 66 getyx(menu->win, item_y, item_x); 67 68 /* We need a marker iff 69 - it is a onevalued menu and it is the current item 70 - or it has a selection value 71 */ 72 wattron(menu->win, (int)menu->back); 73 if (item->value || (item == menu->curitem)) 74 { 75 if (menu->marklen) 76 { 77 /* In a multi selection menu we use the fore attribute 78 for a selected marker that is not the current one. 79 This improves visualization of the menu, because now 80 always the 'normal' marker denotes the current 81 item. */ 82 if (!(menu->opt & O_ONEVALUE) && item->value && item != menu->curitem) 83 { 84 wattron(menu->win, (int)menu->fore); 85 isfore = TRUE; 86 } 87 waddstr(menu->win, menu->mark); 88 if (isfore) 89 { 90 wattron(menu->win, (int)menu->fore); 91 isfore = FALSE; 92 } 93 } 94 } 95 else /* otherwise we have to wipe out the marker area */ 96 for (ch = ' ', i = menu->marklen; i > 0; i--) 97 waddch(menu->win, ch); 98 wattroff(menu->win, (int)menu->back); 99 count += menu->marklen; 100 101 /* First we have to calculate the attribute depending on selectability 102 and selection status 103 */ 104 if (!(item->opt & O_SELECTABLE)) 105 { 106 wattron(menu->win, (int)menu->grey); 107 isgrey = TRUE; 108 } 109 else 110 { 111 if (item->value || item == menu->curitem) 112 { 113 wattron(menu->win, (int)menu->fore); 114 isfore = TRUE; 115 } 116 else 117 { 118 wattron(menu->win, (int)menu->back); 119 isback = TRUE; 120 } 121 } 122 123 waddnstr(menu->win, item->name.str, item->name.length); 124 name_len = _nc_Calculate_Text_Width(&(item->name)); 125 for (ch = ' ', i = menu->namelen - name_len; i > 0; i--) 126 { 127 waddch(menu->win, ch); 128 } 129 count += menu->namelen; 130 131 /* Show description if required and available */ 132 if ((menu->opt & O_SHOWDESC) && menu->desclen > 0) 133 { 134 int m = menu->spc_desc / 2; 135 int cy = -1, cx = -1; 136 int desc_len; 137 138 for (ch = ' ', i = 0; i < menu->spc_desc; i++) 139 { 140 if (i == m) 141 { 142 waddch(menu->win, menu->pad); 143 getyx(menu->win, cy, cx); 144 } 145 else 146 waddch(menu->win, ch); 147 } 148 if (item->description.length) 149 waddnstr(menu->win, item->description.str, item->description.length); 150 desc_len = _nc_Calculate_Text_Width(&(item->description)); 151 for (ch = ' ', i = menu->desclen - desc_len; i > 0; i--) 152 { 153 waddch(menu->win, ch); 154 } 155 count += menu->desclen + menu->spc_desc; 156 157 if (menu->spc_rows > 1) 158 { 159 int j, k, ncy, ncx; 160 161 assert(cx >= 0 && cy >= 0); 162 getyx(menu->win, ncy, ncx); 163 if (isgrey) 164 wattroff(menu->win, (int)menu->grey); 165 else if (isfore) 166 wattroff(menu->win, (int)menu->fore); 167 wattron(menu->win, (int)menu->back); 168 for (j = 1; j < menu->spc_rows; j++) 169 { 170 if ((item_y + j) < getmaxy(menu->win)) 171 { 172 wmove(menu->win, item_y + j, item_x); 173 for (k = 0; k < count; k++) 174 waddch(menu->win, ' '); 175 } 176 if ((cy + j) < getmaxy(menu->win)) 177 (void)mvwaddch(menu->win, cy + j, cx - 1, menu->pad); 178 } 179 wmove(menu->win, ncy, ncx); 180 if (!isback) 181 wattroff(menu->win, (int)menu->back); 182 } 183 } 184 185 /* Remove attributes */ 186 if (isfore) 187 wattroff(menu->win, (int)menu->fore); 188 if (isback) 189 wattroff(menu->win, (int)menu->back); 190 if (isgrey) 191 wattroff(menu->win, (int)menu->grey); 192} 193 194/*--------------------------------------------------------------------------- 195| Facility : libnmenu 196| Function : void _nc_Draw_Menu(const MENU *) 197| 198| Description : Display the menu in its windows 199| 200| Return Values : - 201+--------------------------------------------------------------------------*/ 202MENU_EXPORT(void) 203_nc_Draw_Menu(const MENU *menu) 204{ 205 ITEM *item = menu->items[0]; 206 ITEM *lastvert; 207 ITEM *hitem; 208 chtype s_bkgd; 209 210 assert(item && menu->win); 211 212 s_bkgd = getbkgd(menu->win); 213 wbkgdset(menu->win, menu->back); 214 werase(menu->win); 215 wbkgdset(menu->win, s_bkgd); 216 217 lastvert = (menu->opt & O_NONCYCLIC) ? (ITEM *)0 : item; 218 219 if (item != NULL) 220 { 221 int y = 0; 222 223 do 224 { 225 ITEM *lasthor; 226 227 wmove(menu->win, y, 0); 228 229 hitem = item; 230 lasthor = (menu->opt & O_NONCYCLIC) ? (ITEM *)0 : hitem; 231 232 do 233 { 234 _nc_Post_Item(menu, hitem); 235 236 wattron(menu->win, (int)menu->back); 237 if (((hitem = hitem->right) != lasthor) && hitem) 238 { 239 int i, j, cy, cx; 240 chtype ch = ' '; 241 242 getyx(menu->win, cy, cx); 243 for (j = 0; j < menu->spc_rows; j++) 244 { 245 wmove(menu->win, cy + j, cx); 246 for (i = 0; i < menu->spc_cols; i++) 247 { 248 waddch(menu->win, ch); 249 } 250 } 251 wmove(menu->win, cy, cx + menu->spc_cols); 252 } 253 } 254 while (hitem && (hitem != lasthor)); 255 wattroff(menu->win, (int)menu->back); 256 257 item = item->down; 258 y += menu->spc_rows; 259 260 } 261 while (item && (item != lastvert)); 262 } 263} 264 265/*--------------------------------------------------------------------------- 266| Facility : libnmenu 267| Function : int post_menu(MENU* menu) 268| 269| Description : Post a menu to the screen. This makes it visible. 270| 271| Return Values : E_OK - success 272| E_BAD_ARGUMENT - not a valid menu pointer 273| E_SYSTEM_ERROR - error in lower layers 274| E_NOT_CONNECTED - No items connected to menu 275| E_BAD_STATE - Menu in userexit routine 276| E_POSTED - Menu already posted 277+--------------------------------------------------------------------------*/ 278MENU_EXPORT(int) 279post_menu(MENU *menu) 280{ 281 T((T_CALLED("post_menu(%p)"), (void *)menu)); 282 283 if (!menu) 284 RETURN(E_BAD_ARGUMENT); 285 286 if (menu->status & _IN_DRIVER) 287 RETURN(E_BAD_STATE); 288 289 if (menu->status & _POSTED) 290 RETURN(E_POSTED); 291 292 if (menu->items && *(menu->items)) 293 { 294 int h = 1 + menu->spc_rows * (menu->rows - 1); 295 296 WINDOW *win = Get_Menu_Window(menu); 297 int maxy = getmaxy(win); 298 299 if ((menu->win = newpad(h, menu->width))) 300 { 301 int y = (maxy >= h) ? h : maxy; 302 303 if (y >= menu->height) 304 y = menu->height; 305 if (!(menu->sub = subpad(menu->win, y, menu->width, 0, 0))) 306 RETURN(E_SYSTEM_ERROR); 307 } 308 else 309 RETURN(E_SYSTEM_ERROR); 310 311 if (menu->status & _LINK_NEEDED) 312 _nc_Link_Items(menu); 313 } 314 else 315 RETURN(E_NOT_CONNECTED); 316 317 SetStatus(menu, _POSTED); 318 319 if (!(menu->opt & O_ONEVALUE)) 320 { 321 ITEM **items; 322 323 for (items = menu->items; *items; items++) 324 { 325 (*items)->value = FALSE; 326 } 327 } 328 329 _nc_Draw_Menu(menu); 330 331 Call_Hook(menu, menuinit); 332 Call_Hook(menu, iteminit); 333 334 _nc_Show_Menu(menu); 335 336 RETURN(E_OK); 337} 338 339/*--------------------------------------------------------------------------- 340| Facility : libnmenu 341| Function : int unpost_menu(MENU*) 342| 343| Description : Detach menu from screen 344| 345| Return Values : E_OK - success 346| E_BAD_ARGUMENT - not a valid menu pointer 347| E_BAD_STATE - menu in userexit routine 348| E_NOT_POSTED - menu is not posted 349+--------------------------------------------------------------------------*/ 350MENU_EXPORT(int) 351unpost_menu(MENU *menu) 352{ 353 WINDOW *win; 354 355 T((T_CALLED("unpost_menu(%p)"), (void *)menu)); 356 357 if (!menu) 358 RETURN(E_BAD_ARGUMENT); 359 360 if (menu->status & _IN_DRIVER) 361 RETURN(E_BAD_STATE); 362 363 if (!(menu->status & _POSTED)) 364 RETURN(E_NOT_POSTED); 365 366 Call_Hook(menu, itemterm); 367 Call_Hook(menu, menuterm); 368 369 win = Get_Menu_Window(menu); 370 werase(win); 371 wsyncup(win); 372 373 assert(menu->sub); 374 delwin(menu->sub); 375 menu->sub = (WINDOW *)0; 376 377 assert(menu->win); 378 delwin(menu->win); 379 menu->win = (WINDOW *)0; 380 381 ClrStatus(menu, _POSTED); 382 383 RETURN(E_OK); 384} 385 386/* m_post.c ends here */ 387