1/* $OpenBSD: lib_slk.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ 2 3/**************************************************************************** 4 * Copyright 2020,2022 Thomas E. Dickey * 5 * Copyright 1998-2010,2011 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 * Authors: * 34 * Gerhard Fuernkranz 1993 (original) * 35 * Zeyd M. Ben-Halim 1992,1995 (sic) * 36 * Eric S. Raymond * 37 * Juergen Pfeifer 1996-on * 38 * Thomas E. Dickey * 39 ****************************************************************************/ 40 41/* 42 * lib_slk.c 43 * Soft key routines. 44 */ 45 46#include <curses.priv.h> 47#include <ctype.h> 48 49#ifndef CUR 50#define CUR SP_TERMTYPE 51#endif 52 53MODULE_ID("$Id: lib_slk.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") 54 55#ifdef USE_TERM_DRIVER 56#define NumLabels InfoOf(SP_PARM).numlabels 57#define NoColorVideo InfoOf(SP_PARM).nocolorvideo 58#define LabelWidth InfoOf(SP_PARM).labelwidth 59#define LabelHeight InfoOf(SP_PARM).labelheight 60#else 61#define NumLabels num_labels 62#define NoColorVideo no_color_video 63#define LabelWidth label_width 64#define LabelHeight label_height 65#endif 66 67/* 68 * Free any memory related to soft labels, return an error. 69 */ 70static int 71slk_failed(NCURSES_SP_DCL0) 72{ 73 if ((0 != SP_PARM) && SP_PARM->_slk) { 74 FreeIfNeeded(SP_PARM->_slk->ent); 75 free(SP_PARM->_slk); 76 SP_PARM->_slk = (SLK *) 0; 77 } 78 return ERR; 79} 80 81NCURSES_EXPORT(int) 82_nc_format_slks(NCURSES_SP_DCLx int cols) 83{ 84 int gap, i, x; 85 int max_length; 86 87 if (!SP_PARM || !SP_PARM->_slk) 88 return ERR; 89 90 max_length = SP_PARM->_slk->maxlen; 91 if (SP_PARM->slk_format >= 3) { /* PC style */ 92 gap = (cols - 3 * (3 + 4 * max_length)) / 2; 93 94 if (gap < 1) 95 gap = 1; 96 97 for (i = x = 0; i < SP_PARM->_slk->maxlab; i++) { 98 SP_PARM->_slk->ent[i].ent_x = x; 99 x += max_length; 100 x += (i == 3 || i == 7) ? gap : 1; 101 } 102 } else { 103 if (SP_PARM->slk_format == 2) { /* 4-4 */ 104 gap = cols - (int) (SP_PARM->_slk->maxlab * max_length) - 6; 105 106 if (gap < 1) 107 gap = 1; 108 for (i = x = 0; i < SP_PARM->_slk->maxlab; i++) { 109 SP_PARM->_slk->ent[i].ent_x = x; 110 x += max_length; 111 x += (i == 3) ? gap : 1; 112 } 113 } else { 114 if (SP_PARM->slk_format == 1) { /* 1 -> 3-2-3 */ 115 gap = (cols - (SP_PARM->_slk->maxlab * max_length) - 5) 116 / 2; 117 118 if (gap < 1) 119 gap = 1; 120 for (i = x = 0; i < SP_PARM->_slk->maxlab; i++) { 121 SP_PARM->_slk->ent[i].ent_x = x; 122 x += max_length; 123 x += (i == 2 || i == 4) ? gap : 1; 124 } 125 } else { 126 return slk_failed(NCURSES_SP_ARG); 127 } 128 } 129 } 130 SP_PARM->_slk->dirty = TRUE; 131 132 return OK; 133} 134 135/* 136 * Initialize soft labels. 137 * Called from newterm() 138 */ 139NCURSES_EXPORT(int) 140_nc_slk_initialize(WINDOW *stwin, int cols) 141{ 142 int i; 143 int res = OK; 144 size_t max_length; 145 SCREEN *sp; 146 int numlab; 147 148 T((T_CALLED("_nc_slk_initialize()"))); 149 150 assert(stwin); 151 152 sp = _nc_screen_of(stwin); 153 if (0 == sp) 154 returnCode(ERR); 155 156 assert(TerminalOf(SP_PARM)); 157 158 numlab = NumLabels; 159 160 if (SP_PARM->_slk) { /* we did this already, so simply return */ 161 returnCode(OK); 162 } else if ((SP_PARM->_slk = typeCalloc(SLK, 1)) == 0) 163 returnCode(ERR); 164 165 if (!SP_PARM->slk_format) 166 SP_PARM->slk_format = _nc_globals.slk_format; 167 168 /* 169 * If we use colors, vidputs() will suppress video attributes that conflict 170 * with colors. In that case, we're still guaranteed that "reverse" would 171 * work. 172 */ 173 if ((NoColorVideo & 1) == 0) 174 SetAttr(SP_PARM->_slk->attr, A_STANDOUT); 175 else 176 SetAttr(SP_PARM->_slk->attr, A_REVERSE); 177 178 SP_PARM->_slk->maxlab = (short) ((numlab > 0) 179 ? numlab 180 : MAX_SKEY(SP_PARM->slk_format)); 181 SP_PARM->_slk->maxlen = (short) ((numlab > 0) 182 ? LabelWidth * LabelHeight 183 : MAX_SKEY_LEN(SP_PARM->slk_format)); 184 SP_PARM->_slk->labcnt = (short) ((SP_PARM->_slk->maxlab < MAX_SKEY(SP_PARM->slk_format)) 185 ? MAX_SKEY(SP_PARM->slk_format) 186 : SP_PARM->_slk->maxlab); 187 188 if (SP_PARM->_slk->maxlen <= 0 189 || SP_PARM->_slk->labcnt <= 0 190 || (SP_PARM->_slk->ent = typeCalloc(slk_ent, 191 (size_t) SP_PARM->_slk->labcnt)) 192 == NULL) { 193 free(SP_PARM->_slk->ent); 194 returnCode(slk_failed(NCURSES_SP_ARG)); 195 } 196 197 max_length = (size_t) SP_PARM->_slk->maxlen; 198 for (i = 0; i < SP_PARM->_slk->labcnt; i++) { 199 size_t used = max_length + 1; 200 201 SP_PARM->_slk->ent[i].ent_text = (char *) _nc_doalloc(0, used); 202 if (SP_PARM->_slk->ent[i].ent_text == 0) 203 returnCode(slk_failed(NCURSES_SP_ARG)); 204 memset(SP_PARM->_slk->ent[i].ent_text, 0, used); 205 206 SP_PARM->_slk->ent[i].form_text = (char *) _nc_doalloc(0, used); 207 if (SP_PARM->_slk->ent[i].form_text == 0) 208 returnCode(slk_failed(NCURSES_SP_ARG)); 209 210 if (used > 1) { 211 memset(SP_PARM->_slk->ent[i].form_text, ' ', used - 1); 212 } 213 SP_PARM->_slk->ent[i].form_text[used - 1] = '\0'; 214 215 SP_PARM->_slk->ent[i].visible = (char) (i < SP_PARM->_slk->maxlab); 216 } 217 218 res = _nc_format_slks(NCURSES_SP_ARGx cols); 219 220 if ((SP_PARM->_slk->win = stwin) == NULL) { 221 returnCode(slk_failed(NCURSES_SP_ARG)); 222 } 223 224 /* We now reset the format so that the next newterm has again 225 * per default no SLK keys and may call slk_init again to 226 * define a new layout. (juergen 03-Mar-1999) 227 */ 228 _nc_globals.slk_format = 0; 229 returnCode(res); 230} 231 232/* 233 * Restore the soft labels on the screen. 234 */ 235NCURSES_EXPORT(int) 236NCURSES_SP_NAME(slk_restore) (NCURSES_SP_DCL0) 237{ 238 T((T_CALLED("slk_restore(%p)"), (void *) SP_PARM)); 239 240 if (0 == SP_PARM) 241 returnCode(ERR); 242 if (SP_PARM->_slk == NULL) 243 returnCode(ERR); 244 SP_PARM->_slk->hidden = FALSE; 245 SP_PARM->_slk->dirty = TRUE; 246 247 returnCode(NCURSES_SP_NAME(slk_refresh) (NCURSES_SP_ARG)); 248} 249 250#if NCURSES_SP_FUNCS 251NCURSES_EXPORT(int) 252slk_restore(void) 253{ 254 return NCURSES_SP_NAME(slk_restore) (CURRENT_SCREEN); 255} 256#endif 257