📄 util.c
字号:
/* * Print one line of the prompt in the window within the limits of the * specified right margin. The line will end on a word boundary and a pointer * to the start of the next line is returned, or a NULL pointer if the end of * *prompt is reached. */static const char *print_line(WINDOW *win, chtype *attr, const char *prompt, int lm, int rm, int *x){ const char *wrap_ptr = prompt; const char *test_ptr = prompt; const int *cols = dlg_index_columns(prompt); const int *indx = dlg_index_wchars(prompt); int cur_x = lm; int hidden = 0; int limit = dlg_count_wchars(prompt); int n; *x = 1; /* * Set *test_ptr to the end of the line or the right margin (rm), whichever * is less, and set *wrap_ptr to the end of the last word in the line. */ for (n = 0; n < limit; ++n) { if (*test_ptr == '\n' || *test_ptr == '\0' || cur_x >= (rm + hidden)) break; if (*test_ptr == ' ' && n != 0 && prompt[indx[n - 1]] != ' ') { wrap_ptr = prompt + indx[n]; *x = cur_x; } else if (isOurEscape(test_ptr)) { hidden += 3; n += 2; } cur_x = lm + cols[n + 1]; if (cur_x > (rm + hidden)) break; test_ptr = prompt + indx[n + 1]; } /* * If the line doesn't reach the right margin in the middle of a word, then * we don't have to wrap it at the end of the previous word. */ if (*test_ptr == '\n' || *test_ptr == ' ' || *test_ptr == '\0') { int i = 0; while (&wrap_ptr[++i] < test_ptr) { ; } while (wrap_ptr[i - 1] == ' ') { i--; } wrap_ptr += i; *x += i; } /* * If the line has no spaces, then wrap it anyway at the right margin */ else if (*x == 1 && cur_x >= rm) { *x = rm; wrap_ptr = test_ptr; } /* * Print the line if we have a window pointer. Otherwise this routine * is just being called for sizing the window. */ if (win) { dlg_print_text(win, prompt, (wrap_ptr - prompt - hidden), attr); } /* *x tells the calling function how long the line was */ if (*x == 1) *x = rm; /* Find the start of the next line and return a pointer to it */ test_ptr = wrap_ptr; while (*test_ptr == ' ') test_ptr++; if (*test_ptr == '\n') test_ptr++; return (test_ptr);}static voidjustify_text(WINDOW *win, const char *prompt, int limit_y, int limit_x, int *high, int *wide){ chtype attr = A_NORMAL; int x = (2 * MARGIN); int y = 1; int max_x = 2; int lm = (2 * MARGIN); /* left margin */ int rm = limit_x; /* right margin */ int bm = limit_y; /* bottom margin */ if (win) { rm -= (2 * MARGIN); bm -= (2 * MARGIN); } if (prompt == 0) prompt = ""; while (y <= bm && *prompt) { x = lm; if (*prompt == '\n') { while (*prompt == '\n' && y < bm) { if (*(prompt + 1) != '\0') { ++y; if (win != 0) (void) wmove(win, y, lm); } prompt++; } } else if (win != 0) (void) wmove(win, y, lm); if (*prompt) prompt = print_line(win, &attr, prompt, lm, rm, &x); if (*prompt) { ++y; if (win != 0) (void) wmove(win, y, lm); } max_x = MAX(max_x, x); } /* Set the final height and width for the calling function */ if (high != 0) *high = y; if (wide != 0) *wide = max_x;}/* * Print a string of text in a window, automatically wrap around to the * next line if the string is too long to fit on one line. Note that the * string may contain embedded newlines. */voiddlg_print_autowrap(WINDOW *win, const char *prompt, int height, int width){ justify_text(win, prompt, height, width, (int *) 0, (int *) 0);}/* * Calculate the window size for preformatted text. This will calculate box * dimensions that are at or close to the specified aspect ratio for the prompt * string with all spaces and newlines preserved and additional newlines added * as necessary. */static voidauto_size_preformatted(const char *prompt, int *height, int *width){ int high = 0, wide = 0; float car; /* Calculated Aspect Ratio */ float diff; int max_y = SLINES - 1; int max_x = SCOLS - 2; int max_width = max_x; int ar = dialog_state.aspect_ratio; /* Get the initial dimensions */ justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide); car = (float) (wide / high); /* * If the aspect ratio is greater than it should be, then decrease the * width proportionately. */ if (car > ar) { diff = car / (float) ar; max_x = wide / diff + 4; justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide); car = (float) wide / high; } /* * If the aspect ratio is too small after decreasing the width, then * incrementally increase the width until the aspect ratio is equal to or * greater than the specified aspect ratio. */ while (car < ar && max_x < max_width) { max_x += 4; justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide); car = (float) (wide / high); } *height = high; *width = wide;}/* * Find the length of the longest "word" in the given string. By setting the * widget width at least this long, we can avoid splitting a word on the * margin. */static intlongest_word(const char *string){ int length, result = 0; while (*string != '\0') { length = 0; while (*string != '\0' && !isspace(*string)) { length++; string++; } result = MAX(result, length); string++; } return result;}/* * if (height or width == -1) Maximize() * if (height or width == 0), justify and return actual limits. */static voidreal_auto_size(const char *title, const char *prompt, int *height, int *width, int boxlines, int mincols){ int x = (dialog_vars.begin_set ? dialog_vars.begin_x : 2); int y = (dialog_vars.begin_set ? dialog_vars.begin_y : 1); int title_length = title ? strlen(title) : 0; int nc = 4; int high; int wide; int save_high = *height; int save_wide = *width; if (prompt == 0) { if (*height == 0) *height = -1; if (*width == 0) *width = -1; } if (*height > 0) { high = *height; } else { high = SLINES - y; } if (*width > 0) { wide = *width; } else if (prompt != 0) { wide = MAX(title_length, mincols); if (strchr(prompt, '\n') == 0) { double val = dialog_state.aspect_ratio * strlen(prompt); int tmp = sqrt(val); wide = MAX(wide, tmp); wide = MAX(wide, longest_word(prompt)); justify_text((WINDOW *) 0, prompt, high, wide, height, width); } else { auto_size_preformatted(prompt, height, width); } } else { wide = SCOLS - x; justify_text((WINDOW *) 0, prompt, high, wide, height, width); } if (*width < title_length) { justify_text((WINDOW *) 0, prompt, high, title_length, height, width); *width = title_length; } if (*width < mincols && save_wide == 0) *width = mincols; if (prompt != 0) { *width += nc; *height += boxlines + 2; } if (save_high > 0) *height = save_high; if (save_wide > 0) *width = save_wide;}/* End of real_auto_size() */voiddlg_auto_size(const char *title, const char *prompt, int *height, int *width, int boxlines, int mincols){ real_auto_size(title, prompt, height, width, boxlines, mincols); if (*width > SCOLS) { (*height)++; *width = SCOLS; } if (*height > SLINES) *height = SLINES;}/* * if (height or width == -1) Maximize() * if (height or width == 0) * height=MIN(SLINES, num.lines in fd+n); * width=MIN(SCOLS, MAX(longer line+n, mincols)); */voiddlg_auto_sizefile(const char *title, const char *file, int *height, int *width, int boxlines, int mincols){ int count = 0, len = title ? strlen(title) : 0, nc = 4, numlines = 2; long offset; char ch; FILE *fd; /* Open input file for reading */ if ((fd = fopen(file, "rb")) == NULL) dlg_exiterr("dlg_auto_sizefile: Cannot open input file %s", file); if ((*height == -1) || (*width == -1)) { *height = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0); *width = SCOLS - (dialog_vars.begin_set ? dialog_vars.begin_x : 0); } if ((*height != 0) && (*width != 0)) { (void) fclose(fd); return; } while (!feof(fd)) { offset = 0; while (((ch = getc(fd)) != '\n') && !feof(fd)) if ((ch == TAB) && (dialog_vars.tab_correct)) offset += dialog_state.tab_len - (offset % dialog_state.tab_len); else offset++; if (offset > len) len = offset; count++; } /* now 'count' has the number of lines of fd and 'len' the max lenght */ *height = MIN(SLINES, count + numlines + boxlines); *width = MIN(SCOLS, MAX((len + nc), mincols)); /* here width and height can be maximized if > SCOLS|SLINES because textbox-like widgets don't put all <file> on the screen. Msgbox-like widget instead have to put all <text> correctly. */ (void) fclose(fd);}/* * Draw a rectangular box with line drawing characters. * * borderchar is used to color the upper/left edges. * * boxchar is used to color the right/lower edges. It also is fill-color used * for the box contents. * * Normally, if you are drawing a scrollable box, use menubox_border_attr for * boxchar, and menubox_attr for borderchar since the scroll-arrows are drawn * with menubox_attr at the top, and menubox_border_attr at the bottom. That * also (given the default color choices) produces a recessed effect. * * If you want a raised effect (and are not going to use the scroll-arrows), * reverse this choice. */voiddlg_draw_box(WINDOW *win, int y, int x, int height, int width, chtype boxchar, chtype borderchar){ int i, j; chtype save = getattrs(win); wattrset(win, 0); for (i = 0; i < height; i++) { (void) wmove(win, y + i, x); for (j = 0; j < width; j++) if (!i && !j) (void) waddch(win, borderchar | ACS_ULCORNER); else if (i == height - 1 && !j) (void) waddch(win, borderchar | ACS_LLCORNER); else if (!i && j == width - 1) (void) waddch(win, boxchar | ACS_URCORNER); else if (i == height - 1 && j == width - 1) (void) waddch(win, boxchar | ACS_LRCORNER); else if (!i) (void) waddch(win, borderchar | ACS_HLINE); else if (i == height - 1) (void) waddch(win, boxchar | ACS_HLINE); else if (!j) (void) waddch(win, borderchar | ACS_VLINE); else if (j == width - 1) (void) waddch(win, boxchar | ACS_VLINE); else (void) waddch(win, boxchar | ' '); } wattrset(win, save);}#ifdef HAVE_COLOR/* * Draw shadows along the right and bottom edge to give a more 3D look * to the boxes */voiddlg_draw_shadow(WINDOW *win, int y, int x, int height, int width){ int i, j; if (has_colors()) { /* Whether terminal supports color? */ wattrset(win, shadow_attr); for (i = y + height; i < y + height + SHADOW_ROWS; ++i) { (void) wmove(win, i, x + SHADOW_COLS); for (j = 0; j < width; ++j) (void) waddch(win, CharOf(winch(win))); } for (i = y + SHADOW_ROWS; i < y + height + SHADOW_ROWS; i++) { (void) wmove(win, i, x + width); for (j = 0; j < SHADOW_COLS; ++j) (void) waddch(win, CharOf(winch(win))); } (void) wnoutrefresh(win); }}#endif/* * Allow shell scripts to remap the exit codes so they can distinguish ESC * from ERROR. */voiddlg_exit(int code){ /* *INDENT-OFF* */ static const struct { int code; const char *name; } table[] = { { DLG_EXIT_CANCEL, "DIALOG_CANCEL" }, { DLG_EXIT_ERROR, "DIALOG_ERROR" }, { DLG_EXIT_ESC, "DIALOG_ESC" }, { DLG_EXIT_EXTRA, "DIALOG_EXTRA" }, { DLG_EXIT_HELP, "DIALOG_HELP" }, { DLG_EXIT_OK, "DIALOG_OK" }, }; /* *INDENT-ON* */ unsigned n; char *name; char *temp; long value; for (n = 0; n < sizeof(table) / sizeof(table[0]); n++) { if (table[n].code == code) { if ((name = getenv(table[n].name)) != 0) { value = strtol(name, &temp, 0); if (temp != 0 && temp != name && *temp == '\0') code = value; } break; } } exit(code);}/* quit program killing all tailbg */voiddlg_exiterr(const char *fmt,...){ int retval; va_list ap; end_dialog(); (void) fputc('\n', stderr); va_start(ap, fmt); (void) vfprintf(stderr, fmt, ap); va_end(ap); (void) fputc('\n', stderr); dlg_killall_bg(&retval); (void) fflush(stderr); (void) fflush(stdout); dlg_exit(DLG_EXIT_ERROR);}voiddlg_beeping(void){ if (dialog_vars.beep_signal) { (void) beep(); dialog_vars.beep_signal = 0; }}voiddlg_print_size(int height, int width){ if (dialog_vars.print_siz)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -