Lines Matching +full:y +full:- +full:min

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2021-2023 Alfonso Sabato Siciliano
39 * -1- Error and diagnostic
45 * ----------------------------------------------------
46 * -2- (Unicode) Multicolumn character strings
53 * ----------------------------------------------------
54 * -3- Buttons
62 * ----------------------------------------------------
63 * -4- (Auto) Sizing and (Auto) Position
79 * ----------------------------------------------------
80 * -5- (Dialog) Widget components and utils
85 * update_box(conf, win, y, x, h, w, elev);
88 * ----------------------------------------------------
89 * -6- Dialog init/build, update/draw, destroy
100 * -1- Error and diagnostic
113 strncpy(errorbuffer, str, ERRBUFLEN-1);
121 vsnprintf(errorbuffer, ERRBUFLEN-1, fmt, arg_ptr);
126 * -2- (Unicode) Multicolumn character strings
139 charlen != (size_t)-1 && charlen != (size_t)-2) {
151 void mvwaddwch(WINDOW *w, int y, int x, wchar_t wch)
157 mvwaddwstr(w, y, x, ws);
174 charlen != (size_t)-1 && charlen != (size_t)-2) {
176 return (-1);
204 charlen != (size_t)-1 && charlen != (size_t)-2) {
216 * -3- Buttons
222 width = bs->nbuttons * bs->sizebutton;
223 if (bs->nbuttons > 0)
224 width += (bs->nbuttons - 1) * t.button.minmargin;
230 draw_button(WINDOW *window, int y, int x, int size, const char *text,
246 mvwaddch(window, y, x, t.button.leftdelim);
249 for (i = 1; i < size - 1; i++)
253 mvwaddch(window, y, x + i, t.button.rightdelim);
256 x = x + 1 + ((size - 2 - strcols(text))/2);
258 mvwaddstr(window, y, x, text);
263 mvwaddwch(window, y, x, first);
270 int i, x, startx, y;
273 y = d->h - 2;
275 newmargin = d->w - BORDERS - (d->bs.nbuttons * d->bs.sizebutton);
276 newmargin /= (d->bs.nbuttons + 1);
277 newmargin = MIN(newmargin, t.button.maxmargin);
280 wbuttons = buttons_min_width(&d->bs);
283 wbuttons = d->bs.nbuttons * d->bs.sizebutton;
284 wbuttons += (d->bs.nbuttons + 1) * margin;
287 startx = d->w/2 - wbuttons/2 + newmargin;
288 for (i = 0; i < (int)d->bs.nbuttons; i++) {
289 x = i * (d->bs.sizebutton + margin);
290 draw_button(d->widget, y, startx + x, d->bs.sizebutton,
291 d->bs.label[i], d->bs.first[i], i == d->bs.curr,
292 d->bs.shortcut);
306 d->bs.nbuttons = 0;
307 d->bs.curr = 0;
308 d->bs.sizebutton = 0;
309 d->bs.shortcut = shortcut;
311 if (d->conf->button.left1_label != NULL) {
312 d->bs.label[d->bs.nbuttons] = d->conf->button.left1_label;
313 d->bs.value[d->bs.nbuttons] = BSDDIALOG_LEFT1;
314 d->bs.nbuttons += 1;
317 if (d->conf->button.left2_label != NULL) {
318 d->bs.label[d->bs.nbuttons] = d->conf->button.left2_label;
319 d->bs.value[d->bs.nbuttons] = BSDDIALOG_LEFT2;
320 d->bs.nbuttons += 1;
323 if (d->conf->button.left3_label != NULL) {
324 d->bs.label[d->bs.nbuttons] = d->conf->button.left3_label;
325 d->bs.value[d->bs.nbuttons] = BSDDIALOG_LEFT3;
326 d->bs.nbuttons += 1;
329 if (oklabel != NULL && d->conf->button.without_ok == false) {
330 d->bs.label[d->bs.nbuttons] = d->conf->button.ok_label != NULL ?
331 d->conf->button.ok_label : oklabel;
332 d->bs.value[d->bs.nbuttons] = BSDDIALOG_OK;
333 d->bs.nbuttons += 1;
336 if (d->conf->button.with_extra) {
337 d->bs.label[d->bs.nbuttons] = d->conf->button.extra_label != NULL ?
338 d->conf->button.extra_label : "Extra";
339 d->bs.value[d->bs.nbuttons] = BSDDIALOG_EXTRA;
340 d->bs.nbuttons += 1;
343 if (cancellabel != NULL && d->conf->button.without_cancel == false) {
344 d->bs.label[d->bs.nbuttons] = d->conf->button.cancel_label ?
345 d->conf->button.cancel_label : cancellabel;
346 d->bs.value[d->bs.nbuttons] = BSDDIALOG_CANCEL;
347 if (d->conf->button.default_cancel)
348 d->bs.curr = d->bs.nbuttons;
349 d->bs.nbuttons += 1;
352 if (d->conf->button.with_help) {
353 d->bs.label[d->bs.nbuttons] = d->conf->button.help_label != NULL ?
354 d->conf->button.help_label : "Help";
355 d->bs.value[d->bs.nbuttons] = BSDDIALOG_HELP;
356 d->bs.nbuttons += 1;
359 if (d->conf->button.right1_label != NULL) {
360 d->bs.label[d->bs.nbuttons] = d->conf->button.right1_label;
361 d->bs.value[d->bs.nbuttons] = BSDDIALOG_RIGHT1;
362 d->bs.nbuttons += 1;
365 if (d->conf->button.right2_label != NULL) {
366 d->bs.label[d->bs.nbuttons] = d->conf->button.right2_label;
367 d->bs.value[d->bs.nbuttons] = BSDDIALOG_RIGHT2;
368 d->bs.nbuttons += 1;
371 if (d->conf->button.right3_label != NULL) {
372 d->bs.label[d->bs.nbuttons] = d->conf->button.right3_label;
373 d->bs.value[d->bs.nbuttons] = BSDDIALOG_RIGHT3;
374 d->bs.nbuttons += 1;
377 if (d->bs.nbuttons == 0) {
378 d->bs.label[0] = DEFAULT_BUTTON_LABEL;
379 d->bs.value[0] = DEFAULT_BUTTON_VALUE;
380 d->bs.nbuttons = 1;
383 for (i = 0; i < (int)d->bs.nbuttons; i++) {
384 mbtowc(&first, d->bs.label[i], MB_CUR_MAX);
385 d->bs.first[i] = first;
388 if (d->conf->button.default_label != NULL) {
389 for (i = 0; i < (int)d->bs.nbuttons; i++) {
390 if (strcmp(d->conf->button.default_label,
391 d->bs.label[i]) == 0)
392 d->bs.curr = i;
396 d->bs.sizebutton = MAX(SIZEBUTTON - 2, strcols(d->bs.label[0]));
397 for (i = 1; i < (int)d->bs.nbuttons; i++)
398 d->bs.sizebutton = MAX(d->bs.sizebutton, strcols(d->bs.label[i]));
399 d->bs.sizebutton += 2;
408 for (i = 0; i < bs->nbuttons; i++) {
409 if (towlower(key) == towlower(bs->first[i])) {
410 bs->curr = i;
420 * -4- (Auto) Sizing and (Auto) Position
426 maxheight = conf->shadow ? SCREENLINES - (int)t.shadow.y : SCREENLINES;
428 RETURN_ERROR("Terminal too small, screen lines - shadow <= 0");
430 if (conf->y != BSDDIALOG_CENTER && conf->auto_topmargin > 0)
431 RETURN_ERROR("conf.y > 0 and conf->auto_topmargin > 0");
432 else if (conf->y == BSDDIALOG_CENTER) {
433 maxheight -= conf->auto_topmargin;
435 RETURN_ERROR("Terminal too small, screen lines - top "
437 } else if (conf->y > 0) {
438 maxheight -= conf->y;
440 RETURN_ERROR("Terminal too small, screen lines - "
441 "shadow - y <= 0");
444 maxheight -= conf->auto_downmargin;
446 RETURN_ERROR("Terminal too small, screen lines - Down margins "
456 maxwidth = conf->shadow ? SCREENCOLS - (int)t.shadow.x : SCREENCOLS;
458 RETURN_ERROR("Terminal too small, screen cols - shadow <= 0");
460 if (conf->x > 0) {
461 maxwidth -= conf->x;
463 RETURN_ERROR("Terminal too small, screen cols - shadow "
464 "- x <= 0");
484 #define NL -1
485 #define WS -2
486 #define TB -3
504 tablen = (conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen;
507 if ((tp->words = calloc(maxwords, sizeof(int))) == NULL)
513 if ((tp->wletters = calloc(wtextlen, sizeof(uint8_t))) == NULL)
516 tp->nword = 0;
517 tp->maxline = 0;
518 tp->maxwordcols = 0;
519 tp->hasnewline = false;
524 if (conf->text.escape && is_wtext_attr(wtext + i)) {
529 if (tp->nword + 1 >= maxwords) {
531 tp->words = realloc(tp->words, maxwords * sizeof(int));
532 if (tp->words == NULL)
538 tp->maxwordcols = MAX(wordcols, tp->maxwordcols);
544 tp->words[tp->nword] = wordcols;
545 tp->nword += 1;
554 tp->words[tp->nword] = TB;
558 tp->hasnewline = true;
559 tp->maxline = MAX(tp->maxline, currlinecols);
562 tp->words[tp->nword] = NL;
568 tp->words[tp->nword] = WS;
571 tp->nword += 1;
573 tp->wletters[l] = wcwidth(wtext[i]);
574 wordcols += tp->wletters[l];
580 tp->words[tp->nword] = wordcols;
581 tp->nword += 1;
582 tp->maxwordcols = MAX(wordcols, tp->maxwordcols);
585 tp->maxline = MAX(tp->maxline, currlinecols);
596 int i, j, x, y, z, l, line, maxwidth, tablen;
598 maxwidth = widget_max_width(conf) - BORDERS - TEXTHMARGINS;
599 tablen = (conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen;
602 mincols = MAX(mincols, tp->maxwordcols);
604 (int)conf->auto_minwidth - BORDERS - TEXTHMARGINS);
605 mincols = MIN(mincols, maxwidth);
610 y = 1;
613 for (i = 0; i < tp->nword; i++) {
614 switch (tp->words[i]) {
619 y++;
625 y++;
632 y++;
636 if (tp->words[i] + x <= mincols) {
637 x += tp->words[i];
638 for (z = 0 ; z != tp->words[i]; l++ )
639 z += tp->wletters[l];
640 } else if (tp->words[i] <= mincols) {
641 y++;
642 x = tp->words[i];
643 for (z = 0 ; z != tp->words[i]; l++ )
644 z += tp->wletters[l];
646 for (j = tp->words[i]; j > 0; ) {
647 y = (x == 0) ? y : y + 1;
650 z += tp->wletters[l];
655 j -= z;
666 if (line >= y * (int)conf->text.cols_per_row && y <= maxrows)
671 *h = (tp->nword == 0) ? 0 : y;
672 *w = MIN(mincols, line); /* wtext can be less than mincols */
686 if (bs->nbuttons > 0)
691 maxhtext = widget_max_height(conf) - BORDERS - rowsnotext;
693 maxhtext = rows - BORDERS - rowsnotext;
695 if (bs->nbuttons > 0)
696 maxhtext -= 2;
702 startwtext = MAX(startwtext, wbuttons - TEXTHMARGINS);
705 startwtext = widget_max_width(conf) - BORDERS - TEXTHMARGINS;
708 startwtext = cols - BORDERS - TEXTHMARGINS;
736 int min;
739 min = BORDERS;
742 min += htext;
745 min += hnotext;
749 min += HBUTTONS; /* buttons and their up-border */
752 min = MAX(min, (int)conf->auto_minheight);
754 return (min);
762 int min, delimtitle, wbottomtitle, wtitle;
764 min = 0;
767 if (bs->nbuttons > 0)
768 min += buttons_min_width(bs);
772 min = MAX(min, wtext + TEXTHMARGINS);
774 /* specific widget min width */
775 min = MAX(min, minwidget);
778 if (conf->title != NULL) {
780 wtitle = strcols(conf->title);
781 min = MAX(min, wtitle + 2 + delimtitle);
785 if (conf->bottomtitle != NULL) {
786 wbottomtitle = strcols(conf->bottomtitle);
787 min = MAX(min, wbottomtitle + 4);
791 min += BORDERS;
793 min = MAX(min, (int)conf->auto_minwidth);
795 return (min);
809 RETURN_ERROR("Negative (less than -1) height");
811 *h = MIN(rows, maxheight); /* rows is at most maxheight */
820 RETURN_ERROR("Negative (less than -1) width");
822 *w = MIN(cols, maxwidth); /* cols is at most maxwidth */
845 *h = widget_min_height(conf, htext, hnotext, bs->nbuttons > 0);
846 *h = MIN(*h, widget_max_height(conf));
851 *w = MIN(*w, widget_max_width(conf));
862 if (bs->nbuttons > 0)
869 if (bs->nbuttons > 0)
881 set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
883 int hshadow = conf->shadow ? (int)t.shadow.y : 0;
884 int wshadow = conf->shadow ? (int)t.shadow.x : 0;
886 if (conf->y == BSDDIALOG_CENTER) {
887 *y = SCREENLINES/2 - (h + hshadow)/2;
888 if (*y < (int)conf->auto_topmargin)
889 *y = conf->auto_topmargin;
890 if (*y + h + hshadow > SCREENLINES - (int)conf->auto_downmargin)
891 *y = SCREENLINES - h - hshadow - conf->auto_downmargin;
893 else if (conf->y < BSDDIALOG_CENTER)
894 RETURN_ERROR("Negative begin y (less than -1)");
895 else if (conf->y >= SCREENLINES)
896 RETURN_ERROR("Begin Y under the terminal");
898 *y = conf->y;
900 if (*y + h + hshadow > SCREENLINES)
902 "(begin Y + height (+ shadow) > terminal lines)");
905 if (conf->x == BSDDIALOG_CENTER)
906 *x = SCREENCOLS/2 - (w + wshadow)/2;
907 else if (conf->x < BSDDIALOG_CENTER)
908 RETURN_ERROR("Negative begin x (less than -1)");
909 else if (conf->x >= SCREENCOLS)
912 *x = conf->x;
923 if (set_widget_size(d->conf, d->rows, d->cols, &d->h, &d->w) != 0)
925 if (set_widget_autosize(d->conf, d->rows, d->cols, &d->h, &d->w,
926 d->text, htext, &d->bs, hnotext, minw) != 0)
928 if (widget_checksize(d->h, d->w, &d->bs, hnotext, minw) != 0)
930 if (set_widget_position(d->conf, &d->y, &d->x, d->h, d->w) != 0)
937 * -5- Widget components and utilities
943 if ((clear = newwin(d->h, d->w, d->y, d->x)) == NULL)
948 if (d->conf->shadow) {
949 mvwin(clear, d->y + t.shadow.y, d->x + t.shadow.x);
967 hconf.ascii_lines = conf->ascii_lines;
968 hconf.no_lines = conf->no_lines;
969 hconf.shadow = conf->shadow;
970 hconf.text.escape = conf->text.escape;
973 if (conf->key.f1_message != NULL)
974 output = bsddialog_msgbox(&hconf, conf->key.f1_message, 0, 0);
976 if (output != BSDDIALOG_ERROR && conf->key.f1_file != NULL)
977 output = bsddialog_textbox(&hconf, conf->key.f1_file, 0, 0);
989 if (conf->no_lines)
992 if (conf->ascii_lines) {
995 setcchar(&vline, L"-", 0, 0, NULL);
1019 mvwadd_wch(win, 0, w-1, tr);
1020 mvwvline_set(win, 1, w-1, rs, h-2);
1021 mvwadd_wch(win, h-1, w-1, br);
1022 mvwhline_set(win, h-1, 1, bs, w-2);
1027 update_box(struct bsddialog_conf *conf, WINDOW *win, int y, int x, int h, int w,
1032 mvwin(win, y, x);
1039 pnoutrefresh(d->textpad, ytext, xtext,
1040 d->y + BORDER + upnotext,
1041 d->x + BORDER + TEXTHMARGIN,
1042 d->y + d->h - 1 - downnotext - BORDER,
1043 d->x + d->w - TEXTHMARGIN - BORDER);
1047 * -6- Dialog init/build, update/draw, destroy
1051 if (d->conf->sleep > 0)
1052 sleep(d->conf->sleep);
1054 delwin(d->textpad);
1055 delwin(d->widget);
1056 if (d->conf->shadow)
1057 delwin(d->shadow);
1059 if (d->conf->clear)
1062 if (d->conf->get_height != NULL)
1063 *d->conf->get_height = d->h;
1064 if (d->conf->get_width != NULL)
1065 *d->conf->get_width = d->w;
1077 wattron(win, bsddialog_color(wtext[2] - L'0', bg, 0));
1128 print_string(WINDOW *win, int *rows, int cols, int *y, int *x, wchar_t *str,
1155 *y = *y + 1;
1156 if (*y >= *rows) {
1157 *rows = *y + 1;
1174 mvwaddwstr(win, *y, j, ws);
1175 strwidth -= charwidth;
1187 int i, j, z, rows, cols, x, y, tablen;
1197 tablen = (conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen;
1199 i = j = x = y = 0;
1206 print_string(pad, &rows, cols, &y, &x, string,
1207 conf->text.escape);
1216 y++;
1217 j = -1;
1223 y++;
1227 j = -1;
1233 y++;
1235 j = -1;
1238 if (y >= rows) {
1239 rows = y + 1;
1258 if (d->conf->ascii_lines) {
1259 setcchar(&ts, L"-", 0, 0, NULL);
1268 if (d->conf->shadow) {
1269 wclear(d->shadow);
1270 wresize(d->shadow, d->h, d->w);
1271 mvwin(d->shadow, d->y + t.shadow.y, d->x + t.shadow.x);
1272 wnoutrefresh(d->shadow);
1275 wclear(d->widget);
1276 wresize(d->widget, d->h, d->w);
1277 mvwin(d->widget, d->y, d->x);
1278 draw_borders(d->conf, d->widget, RAISED);
1280 if (d->conf->title != NULL) {
1281 if ((wtitle = strcols(d->conf->title)) < 0)
1283 if (t.dialog.delimtitle && d->conf->no_lines == false) {
1284 wattron(d->widget, t.dialog.lineraisecolor);
1285 mvwadd_wch(d->widget, 0, d->w/2 - wtitle/2 -1, &rtee);
1286 wattroff(d->widget, t.dialog.lineraisecolor);
1288 wattron(d->widget, t.dialog.titlecolor);
1289 mvwaddstr(d->widget, 0, d->w/2 - wtitle/2, d->conf->title);
1290 wattroff(d->widget, t.dialog.titlecolor);
1291 if (t.dialog.delimtitle && d->conf->no_lines == false) {
1292 wattron(d->widget, t.dialog.lineraisecolor);
1293 wadd_wch(d->widget, &ltee);
1294 wattroff(d->widget, t.dialog.lineraisecolor);
1298 if (d->bs.nbuttons > 0) {
1299 if (d->conf->no_lines == false) {
1300 wattron(d->widget, t.dialog.lineraisecolor);
1301 mvwadd_wch(d->widget, d->h-3, 0, &ltee);
1302 mvwhline_set(d->widget, d->h-3, 1, &ts, d->w-2);
1303 wattroff(d->widget, t.dialog.lineraisecolor);
1305 wattron(d->widget, t.dialog.linelowercolor);
1306 mvwadd_wch(d->widget, d->h-3, d->w-1, &rtee);
1307 wattroff(d->widget, t.dialog.linelowercolor);
1312 if (d->conf->bottomtitle != NULL) {
1313 if ((wbottomtitle = strcols(d->conf->bottomtitle)) < 0)
1315 wattron(d->widget, t.dialog.bottomtitlecolor);
1316 wmove(d->widget, d->h - 1, d->w/2 - wbottomtitle/2 - 1);
1317 waddch(d->widget, ' ');
1318 waddstr(d->widget, d->conf->bottomtitle);
1319 waddch(d->widget, ' ');
1320 wattroff(d->widget, t.dialog.bottomtitlecolor);
1323 wnoutrefresh(d->widget);
1325 wclear(d->textpad);
1327 wresize(d->textpad, 1, d->w - BORDERS - TEXTHMARGINS);
1329 if (print_textpad(d->conf, d->textpad, d->text) != 0)
1332 d->built = true;
1343 d->built = false;
1344 d->conf = conf;
1345 d->rows = rows;
1346 d->cols = cols;
1347 d->text = CHECK_STR(text);
1348 d->bs.nbuttons = 0;
1350 if (d->conf->shadow) {
1351 if ((d->shadow = newwin(1, 1, 1, 1)) == NULL)
1353 wbkgd(d->shadow, t.shadow.color);
1356 if ((d->widget = newwin(1, 1, 1, 1)) == NULL)
1358 wbkgd(d->widget, t.dialog.color);
1361 if ((d->textpad = newpad(1, 1)) == NULL)
1363 wbkgd(d->textpad, t.dialog.color);