1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 /*LINTLIBRARY*/ 43 44 #include <sys/types.h> 45 #include <stdlib.h> 46 #include "curses_inc.h" 47 48 /* 49 * Initialize usage of soft labels 50 * This routine should be called before each call of newscreen 51 * or initscr to initialize for the next terminal. 52 * 53 * ng: number of groupings. If gp is NULL, it denotes one 54 * of two default groupings: 55 * 0: - - - - - - - - 56 * 1: - - - - - - - - 57 * gp: groupings. 58 */ 59 60 static void _init_slk_func(void); 61 static int _slk_setpos(int, short *); 62 static int _ngroups, _groups[LABMAX]; 63 64 int 65 slk_start(int ng, int *gp) 66 { 67 int i = 0, j = 0; 68 69 if (gp == NULL) { 70 switch (ng) { 71 case 2 : 72 _ngroups = 2; 73 _groups[0] = 4; 74 _groups[1] = 4; 75 break; 76 77 case 3 : 78 no_format : 79 _ngroups = 3; 80 _groups[0] = 3; 81 _groups[1] = 2; 82 _groups[2] = 3; 83 break; 84 85 default : 86 if (label_format) { 87 int k; 88 char ch1[3], *ch = label_format; 89 90 /*CONSTCOND*/ 91 while (TRUE) { 92 if ((*ch == ',') || 93 (*ch == '\0')) { 94 ch1[i] = '\0'; 95 if ((k = atoi(ch1)) <= 96 0) 97 goto err; 98 _groups[j++] = k; 99 i = 0; 100 if (*ch == '\0') { 101 break; 102 } 103 } else 104 ch1[i++] = *ch++; 105 } 106 } else 107 goto no_format; 108 break; 109 } 110 } else { 111 for (; i < ng; i++) { 112 if ((j += gp[i]) > LABMAX) 113 err : 114 return (ERR); 115 _groups[i] = gp[i]; 116 } 117 _ngroups = ng; 118 } 119 120 /* signal newscreen() */ 121 _slk_init = _init_slk_func; 122 return (OK); 123 } 124 125 static void 126 _init_slk_func(void) 127 { 128 int i, len, num; 129 SLK_MAP *slk; 130 char *cp, *ep; 131 WINDOW *win; 132 133 /* clear this out to ready for next time */ 134 _slk_init = NULL; 135 136 /* get space for slk structure */ 137 if ((slk = (SLK_MAP *) malloc(sizeof (SLK_MAP))) == NULL) { 138 curs_errno = CURS_BAD_MALLOC; 139 #ifdef DEBUG 140 strcpy(curs_parm_err, "_init_slk_func"); 141 #endif /* DEBUG */ 142 return; 143 } 144 145 /* compute actual number of labels */ 146 num = 0; 147 for (i = 0; i < _ngroups; i++) 148 num += _groups[i]; 149 150 /* max label length */ 151 if (plab_norm && (label_height * label_width >= LABLEN) && 152 (num_labels >= num)) { 153 win = NULL; 154 goto next; 155 } else { 156 if ((win = newwin(1, COLS, LINES - 1, 0)) == NULL) 157 goto err; 158 win->_leave = TRUE; 159 (void) wattrset(win, A_REVERSE | A_DIM); 160 161 /* remove one line from the screen */ 162 LINES = --SP->lsize; 163 if ((len = (COLS - 1) / (num + 1)) > LABLEN) { 164 next : 165 len = LABLEN; 166 } 167 } 168 169 /* positions to place labels */ 170 if (len <= 0 || num <= 0 || (_slk_setpos(len, slk->_labx) == ERR)) { 171 if (win != NULL) 172 (void) delwin(win); 173 err : 174 free(slk); 175 } else { 176 /* LINTED */ 177 slk->_num = (short) num; 178 /* LINTED */ 179 slk->_len = (short) len; 180 181 for (i = 0; i < num; ++i) { 182 cp = slk->_ldis[i]; 183 ep = cp + len; 184 for (; cp < ep; ++cp) 185 *cp = ' '; 186 *ep = '\0'; 187 slk->_lval[i][0] = '\0'; 188 slk->_lch[i] = TRUE; 189 } 190 191 slk->_changed = TRUE; 192 slk->_win = win; 193 194 _do_slk_ref = _slk_update; 195 _do_slk_tch = slk_touch; 196 _do_slk_noref = slk_noutrefresh; 197 198 SP->slk = slk; 199 } 200 } 201 202 203 /* 204 * Compute placements of labels. The general idea is to spread 205 * the groups out evenly. This routine is designed for the day 206 * when > 8 labels and other kinds of groupings may be desired. 207 * 208 * The main assumption behind the algorithm is that the total 209 * # of labels in all the groups is <= LABMAX. 210 * 211 * len: length of a label 212 * labx: to return the coords of the labels. 213 */ 214 215 static int 216 _slk_setpos(int len, short *labx) 217 { 218 int i, k, n, spread, left, begadd; 219 int grpx[LABMAX]; 220 221 /* compute starting coords for each group */ 222 grpx[0] = 0; 223 if (_ngroups > 1) { 224 /* spacing between groups */ 225 for (i = 0, n = 0; i < _ngroups; ++i) 226 n += _groups[i] * (len + 1) - 1; 227 if ((spread = (COLS - (n + 1))/(_ngroups - 1)) <= 0) 228 return (ERR); 229 left = (COLS-(n + 1)) % (_ngroups - 1); 230 begadd = (_ngroups / 2) - (left / 2); 231 232 /* coords of groups */ 233 for (i = 1; i < _ngroups; ++i) { 234 grpx[i] = grpx[i - 1] + (_groups[i - 1] * 235 (len + 1) - 1) + spread; 236 if (left > 0 && i > begadd) { 237 grpx[i]++; 238 left--; 239 } 240 } 241 } 242 243 /* now set coords of each label */ 244 n = 0; 245 for (i = 0; i < _ngroups; ++i) 246 for (k = 0; k < _groups[i]; ++k) 247 labx[n++] = grpx[i] + k * (len + 1); 248 return (OK); 249 } 250